
У меня есть два .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
не работали так, как хотелось бы. Поэтому мне приходится читать его дословно, что я и пытался сделать согласно ответу Мартина Шаррера здесь:Аргументы команды управления.
\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
}
и я бы использовал это в другом макросе. Однако, тестируя его отдельно, я получаю ошибку, что Use of \all
не соответствует своему определению \alltext
, и я думаю, что я упускаю здесь важный момент.
- Я думаю, что я поместил определение
\all@text
после\alltext
, чтобы я мог закрыть группу, которая, по моему мнению, мне нужна для определения региона, где изменяются каткоды. Но я не вижу, почему\all@text
должно быть известно уже в определении\alltext
? - До сих пор я понимал, что
\@...
команды — это примитивные команды, но я думал, что это всего лишь нотация. Есть ли что-то еще? - есть ли способ заставить этот код работать?
решение1
Я не уверен, что я что-то упустил в вашей настройке, но вам вообще нужно объединять два .bib
файла? Если они названы, скажем, biblio1.bib
и biblio2.bib
, BibTeX и LaTeX могут легко получить доступ к обоим файлам через оператор
\bibliography{biblio1,biblio2}
Если вы используете biblatex
пакет, я понимаю, что предпочтительным стилем будет использование пары отдельных \addbibresource
операторов (см. раздел 3.6.1 пакетаруководство):
\addbibresource{biblio1.bib}
\addbibresource{biblio2.bib}
.bib
Обратите внимание, что при использовании команды необходимо указывать расширение имени файла \addbibresource
, тогда как при использовании команды указывать это расширение не следует \bibliography
.
решение2
Если вы действительно хотите сделать это на уровне TeX (что на самом деле не обязательно, поскольку вы можете ввести столько .bib
файлов, сколько захотите), вот набор макросов, которые это делают. Вы можете указать в качестве обязательного аргумента \concatbib
любое количество имен файлов bib (без расширения), разделенных запятыми.
\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 (или любую другую оболочку или терминал) в соответствующем каталоге и введите:
cat bibone.bib bibtwo.bib >MyBib.bib
В Windows откройте командную строку CMD и введите:
type bibone.bib bibtwo.bib >MyBib.bib
В обеих системах вы также можетедобавитьв существующий MyBib.bib, перенаправив вывод >>
вместо >
.