从 LaTeX 中合并 bib 文件

从 LaTeX 中合并 bib 文件

我有两个.bib文件想要用在我的参考书目中。条目不重叠。我找到了不少关于此问题的论坛主题,但没有一个真正让我满意。所以我的想法是将两个文件合并为一个.bib文件,我将在 中使用该文件.tex。最方便的是,这将在 LaTeX 中完成(因此我不使用bibtool或参考软件)。因此,我制作了一个宏来合并两个文件:

\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之后,\alltext这样我就可以关闭该组,根据我的理解,我需要定义 catcodes 被更改的区域。但我不明白为什么\all@text的定义中应该已经知道\alltext
  • 到目前为止,我明白\@...命令是原始命令,但我认为这只是一种符号。还有更多吗?
  • 有没有什么办法可以让这段代码运行起来?

答案1

我不确定我是否遗漏了你的设置,但你真的需要合并这两个.bib文件吗?如果它们被命名为biblio1.bibbiblio2.bib,BibTeX 和 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 中实现这一点,而只是使用基本的操作系统功能(不需要 bibtool 或其他花哨的东西):

在 Linux/UNIX/MacOS 上,在相应目录中打开 bash(或任何 shell 或终端)并输入:

cat bibone.bib bibtwo.bib >MyBib.bib

在 Windows 上,打开 CMD 提示符并输入:

type bibone.bib bibtwo.bib >MyBib.bib

在这两个系统上您还可以附加>>通过使用而不是 来重定向输出到现有的 MyBib.bib >

相关内容