LaTeX 内から bib ファイルをマージする

LaTeX 内から bib ファイルをマージする

.bib参考文献に使用したいファイルが 2 つあります。エントリは重複しません。これについてはフォーラムのトピックをいくつか見つけましたが、どれも満足できるものではありませんでした。そこで、2 つのファイルを 1 つの.bibファイルに結合して、 で使用することにしました.tex。最も便利なのは、これを LaTeX 内から実行することです (そのためbibtool、 や参照ソフトウェアは使用しません)。そこで、2 つのファイルを結合するマクロを作成しました。

\newwrite\bibwrite
\newcommand{\concatbib}[2]{%
  \begingroup
  \IfFileExists{#1}%
    {\CatchFileDef{\bibone}{#1}{}} 
    {\let\bibone\empty}
  \IfFileExists{#2}%
    {\CatchFileDef{\bibtwo}{#2}{}}
    {\let\bibtwo\empty}%
  \immediate\openout\bibwrite=MyBib.bib\relax
  \immediate\write\bibwrite{\bibone \bibtwo}%
  \immediate\closeout\bibwrite
  \endgroup
}

これは基本的に別の質問から引用したものです(ファイルを「追加」モードで開くにはどうすればいいですか?)。ここで問題となるのは、Latex がファイルの内容を解釈しようとするため、 などが\noexpand期待\detokenizeどおりに動作しないことです。そのため、これを逐語的に読み取る必要がありますが、Martin Scharrer の回答に従って試してみました。制御コマンド引数

\def\alltext{
  \begingroup
  \let\do\@makeother % define \do to change the category code of its argument to 'other'
  \dospecials % makro that is a string of every special character preceeded with \do -> all catcodes are changed
  \all@text
}
\def\all@text#1{
  \endgroup
  #1
}

\allそして、これを他のマクロ内で使用します。ただし、単独でテストすると、「 の使用がその定義と一致しない」というエラーが発生し\alltext、ここで大きなポイントを見逃していると思います。

  • グループを閉じるためにの定義を\all@textの後に置いたと思いますが、私の理解では、catcodes が変更される領域を定義する必要があります。しかし、 の定義で がすでにわかっている必要がある\alltext理由がわかりません。\all@text\alltext
  • これまで、\@...コマンドはプリミティブコマンドであると理解していましたが、それは単なる表記法だと思っていました。それ以上の何かがあるのでしょうか?
  • そのコードを動作させる方法はありますか?

答え1

設定について何か見落としているのかどうかわかりませんが、2つの.bibファイルを結合する必要はあるのでしょうか?たとえば、とという名前であれば、biblio1.bibBibTeXbiblio2.bibとLaTeXは次のステートメントで簡単に両方のファイルにアクセスできます。

\bibliography{biblio1,biblio2}

パッケージを使用する場合biblatex、別々のステートメントのペアを使用するのが望ましいスタイルだと理解しています\addbibresource(パッケージのセクション3.6.1を参照)。マニュアル):

\addbibresource{biblio1.bib}
\addbibresource{biblio2.bib}

.bibコマンドを使用する場合はファイル名拡張子を指定する必要があることに注意してください\addbibresource。一方、 コマンドを使用する場合は、この拡張子を指定する必要はありません\bibliography

答え2

本当に TeX レベルで実行したい場合 (必要な数のファイルを入力できるため、これは実際には必要ありません)、これを実行するマクロのセットを次に示します。カンマで区切られた任意の数の bib ファイル名 (拡張子なし).bibを必須引数として指定できます。\concatbib

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
% The document level command
\NewDocumentCommand{\concatbib}{ O{output} m }
 {
  \heinrich_concatbib:nn { #1 } { #2 }
 }

% Variables and messages
\ior_new:N \l__heinrich_input_stream
\iow_new:N \l__heinrich_output_stream
\msg_new:nnnn { concatbib } { file-exist }
  { File~`#1'~exists.~Not~overwriting.}
  { The~file~`#1'~already~exists.~I'll~ignore~this~command. }

% Internal functions
% First we check that the named output file doesn't exist 
\cs_new_protected:Npn \heinrich_concatbib:nn #1 #2
 {
  \file_if_exist:nTF { #1.bib }
   {
    \msg_error:nnn { concatbib } { file-exist } { #1.bib }
   }
   {
    \__heinrich_concatbib_aux:nn { #1 } { #2 }
   }
 }
% If we're writing, we open an output stream and cycle
% through the second argument, a comma separated list
% of bib file names
\cs_new_protected:Npn \__heinrich_concatbib_aux:nn #1 #2
 {
  \iow_open:Nn \l__heinrich_output_stream { #1.bib }
  \clist_map_inline:nn { #2 } { \__heinrich_read_write:n { ##1 } }
  \iow_close:N \l__heinrich_output_stream
 }
% At each step we read each line of the current .bib file
% and write it to the output stream
\cs_new_protected:Npn \__heinrich_read_write:n #1
 {
  \ior_open:Nn \l__heinrich_input_stream { #1.bib }
  \ior_str_map_inline:Nn \l__heinrich_input_stream
   { \iow_now:Nn \l__heinrich_output_stream { ##1 } }
  \ior_close:N \l__heinrich_input_stream
 }
\ExplSyntaxOff

% This will concatenate in `output.bib'
\concatbib{foo1,foo2}

% This will concatenate in `foo.bib'
\concatbib[foo]{foo1,foo2}

答え3

うーん... 私は、タスクに適したツールを使用するという考え方を強く支持しています。したがって、知的に啓発されるとはいえ、これを LaTeX で実装するのではなく、基本的な OS 機能を使用するだけにします (bibtool やその他の高度な機能は必要ありません)。

Linux/UNIX/MacOS では、それぞれのディレクトリで bash (または任意のシェルやターミナル) を開き、次のように入力します。

cat bibone.bib bibtwo.bib >MyBib.bib

Windows では、CMD プロンプトを開いて次のように入力します。

type bibone.bib bibtwo.bib >MyBib.bib

どちらのシステムでも、追加>>の代わりにを使用して出力をリダイレクトすることで、既存の MyBib.bib に追加します>

関連情報