如何在“biblatex.cfg”文件中的任何字段前面添加/附加文本?

如何在“biblatex.cfg”文件中的任何字段前面添加/附加文本?

我想要一种可移植的方式将文本添加到参考书目中任何项目的任何字段的前面/后面,这意味着它必须进入一个biblatex.cfg使用包时自动读取的特殊文件biblatex

biblatex.cfg(无法用 生成filecontents):

\ExecuteBibliographyOptions{sorting=nyt}
\DeclareSourcemap{
  \maps{
    \map[overwrite]{
      \step[fieldsource=url, final]
      % \step[fieldset=author, fieldvalue={|prepend|}, prepend]
      \step[fieldset=author, fieldvalue={|append|}, append] % That actually works
    }
  }
}

MWE(代表lualatex):

\documentclass{article}

\begin{filecontents*}{example.bib}
@book{sometag,
  author = {author},
  title = {title},
  year = {year},
  url = {url},
}
\end{filecontents*}

\usepackage{biblatex}

\addbibresource{example.bib}

% I don't understand why it doesn't work but it's not portable anyway.
% \usepackage{xpatch}
% \xpretofieldformat{author}{|prepend|}{}{}
% \xapptofieldformat{author}{|append|}{}{}

\nocite{*}

\begin{document}
\printbibliography{}
\end{document}

输出:

输出

期望输出:

期望输出

答案1

我不认为存在一种通用的方法可以在其中添加或附加任意字段biblatex

我首先想到的是最通用的解决方案是与问题中所示的源映射类似的源映射。虽然append存在(并将按照您的示例*所示工作),但没有prepend,但可以使用正则表达式匹配来模拟这样的功能。

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{biblatex}

\DeclareSourcemap{
  \maps{
    \map[overwrite]{
      \step[fieldsource=title,
            match=\regexp{\A(.*)\Z},
            replace=|pre text|$1|post text|]
    }
  }
}

\begin{filecontents*}{\jobname.bib}
@book{sometag,
  author = {author},
  title  = {title},
  year   = {2023},
  url    = {url},
}
\end{filecontents*}
\addbibresource{\jobname.bib}

\nocite{*}

\begin{document}
\printbibliography
\end{document}

作者。| 前言 | 标题 | 文章正文 |。2023。url:url。

对于简单的文本,例如pre textpost text你可以使用

replace=|pre text|$1|post text|

如果你有更复杂的宏,这些宏是不可扩展的(或者想要使用一些正则表达式特性),你最好将文本换行\regexp,但这样空格就会被规范化所占用,所以你必须使用\x{20},这样字符的正则表达式含义就会被激活,这意味着你需要转义\等等

replace=\regexp{|pre\x{20}\\textbf{text}|$1|post\x{20}text|}

将产生

作者。| 前言 | 标题 | 文章正文 |。2023。url:url。

在上面的例子中。

然而,sourcemap 解决方案也有缺点。

  • .bib读取文件时,文本会添加到字段中。这意味着它会影响排序和所有其他.bib基于数据的操作。

  • 文本将成为字段的一部分,这意味着它将被格式化为字段。在示例中,“前”和“后”也以斜体显示。

  • 对于姓名列表字段(例如)author,添加的文本将被解析为姓名的一部分。这可能会导致非常奇怪的结果,例如

    \documentclass{article}
    \usepackage[T1]{fontenc}
    \usepackage{biblatex}
    
    \DeclareSourcemap{
      \maps{
        \map[overwrite]{
          \step[fieldsource=author,
                match=\regexp{\A(.*)\Z},
                replace=|pre|$1|post|]
        }
      }
    }
    
    \begin{filecontents*}{\jobname.bib}
    @book{sometag,
      author = {Jane Doe and Elk, Anne},
      title  = {title},
      year   = {2023},
      url    = {url},
    }
    \end{filecontents*}
    \addbibresource{\jobname.bib}
    
    \nocite{*}
    
    \begin{document}
    \printbibliography
    \end{document}
    

    |pre|Jane Doe 和 Anne|post| Elk。标题。2023。url:url。

    由于您不知道名称的格式如何,因此您无法轻易反驳这一点。

因此,对于大多数意图和目的而言,源映射可能都无法满足要求。

然而,所有其他解决方案在某种程度上都会依赖于风格。

  • 所有biblatex标准样式和几乎所有编写良好的第三方样式都有一个begentryfinentrybibmacro,分别在条目的开头和结尾执行。它们可以重新定义为在该点打印任意文本。以下示例begentry可以在以下位置找到一个示例如何在参考文献中打印 shortauthor?

  • 通常,样式可以采用两种方式在字段之前或之后打印文本。根据该文本是否应被视为“字段输出的一部分”,其中一种解决方案可能比另一种更合适。

    • 找出哪个 bibmacro 打印该字段,并在相关的\printfield,\printlist\printnames调用之前或之后插入文本。显然,这与样式高度相关。

    • 使用字段格式添加文本,例如\DeclareFieldFormat{title}{pre-#1-post}。这将覆盖样式所做的操作,并且由于类型特定的格式(参见从样式中删除引号)。

这里讨论的所有内容都可以使用biblatex.cfg,但显然并不是所有的解决方案都对您想要使用的所有可能的风格起作用。


最后,我认为只有您能更详细地描述您的实际用例(或至少是提出这个问题的动机),我们才能给您一个有用的答案。重点是按照您使用的样式中定义的格式biblatex显示您的.bib数据。它不是在其中插入任意文本 - 除非这是样式想要的(但您需要自定义要使用的特定样式)。


* 该示例在我的计算机上无法运行,因为filecontents拒绝写出biblatex.cfg,因为全局变量biblatex.cfg已经存在。显然 LaTeX 认为它会覆盖该文件。如果我手动生成包含所示内容的文件,我会收到有关 的错误prepend,但当我删除该行时,append会按预期工作。

答案2

我想分享我的解决方案以防有人遇到类似的问题。

url实际上,如果该字段存在,我只需要在项目的开头添加一些文本。但是选定的答案显然不适合我的情况。这是因为我的一些来源没有作者字段,因此解决方案变得更加困难/庞大。好吧,也就是说,如果解决方案不是这个:

% Solution 1
\def\prepend{prepend} % Any text goes here

\renewbibmacro{begentry}{\iffieldundef{url}{}{\prepend\addspace}}

但是,例如这个:

我找到了\newbibmacro*{author}和的定义(出现在日志中):\newbibmacro*{title}texlive/20*/texmf-dist/tex/latex/biblatex/biblatex.def

\newbibmacro*{author}{%
  \ifboolexpr{
    test \ifuseauthor
    and
    not test {\ifnameundef{author}}
  }
    {\printnames{author}%
     \iffieldundef{authortype}
       {}
       {\setunit{\printdelim{authortypedelim}}%
        \usebibmacro{authorstrg}}}
    {}}
\newbibmacro*{title}{%
  \ifboolexpr{
    test {\iffieldundef{title}}
    and
    test {\iffieldundef{subtitle}}
  }
    {}
    {\printtext[title]{%
       \printfield[titlecase]{title}%
       \setunit{\subtitlepunct}%
       \printfield[titlecase]{subtitle}}%
     \newunit}%
  \printfield{titleaddon}}

然后我重新定义(并重新格式化)它们,如下所示:

% Solution 2
\def\prepend{prepend} % Any text goes here

\renewbibmacro*{author}{%
  \ifboolexpr{
    test \ifuseauthor
    and
    not test {\ifnameundef{author}}
  }{%
    \iffieldundef{url}{}{\prepend\addspace}%
    \printnames{author}%
    \iffieldundef{authortype}{}{%
      \setunit{\printdelim{authortypedelim}}%
      \usebibmacro{authorstrg}%
    }%
  }{}%
}

\renewbibmacro*{title}{%
  \ifboolexpr{
    test {\iffieldundef{title}}
    and
    test {\iffieldundef{subtitle}}
  }
  {}
  {%
    \ifboolexpr{% Simple \iffieldundef{author}{}{} didn't work in some cases
      test \ifuseauthor
      and
      not test {\ifnameundef{author}}
    }{}{%
      \iffieldundef{url}{}{\prepend\addspace}%
    }%
    \printtext[title]{%
      \printfield[titlecase]{title}%
      \setunit{\subtitlepunct}%
      \printfield[titlecase]{subtitle}%
    }%
    \newunit%
  }%
  \printfield{titleaddon}%
}

现在,即使作者不存在(但标题存在),\prepend文本也会添加到左侧。

@book{sometag1,
  author = {author1},
  title = {title1},
  year = {year1},
}
@book{sometag2,
  author = {author2},
  title = {title2},
  year = {year2},
  url = {url2},
}
@book{sometag3,
  author = {author3},
  title = {title3},
  year = {year3},
}
@book{sometag4,
  title = {title4},
  year = {year4},
}
@book{sometag5,
  title = {title5},
  year = {year5},
  url = {url5},
}

正确的输出

相关内容