更新

更新

我有一个关于操作 bst 文件以删除中间名首字母后的句点的问题。假设以下 .bib 文件条目:

@BOOK{author1999book,
title = {Very Informative and Handsome Book},
publisher = {College Town, ST: College University Press},
year = {1999},
author = {First M. Last},
}

我一直在对apa.bst文件进行各种修改,以创建一个与特定期刊相匹配的 bst 文件。他们要求的一件事是中间名首字母后面不能有句号。因此,他们的参考书目部分样式如下:

姓氏,名字 M (1999)内容丰富且精美的书. 大学城,圣路易斯县:大学城出版社。

我已经修改了apa.bst文件以解决其他格式问题(年份周围的括号、标题的大写)。剩下的就是中间名首字母后的句号问题。

现在,我只需在 .bib 文件条目中删除中间名首字母后面的句点即可。不过,我想做的是在 *.bst 文件中找到一种方法来做到这一点。可以吗?我之所以问这个问题,是因为如果是,几种 bst 样式实际上会包含该句点不是在 *.bib 文件中。我想要做的是让 bst 文件从中间首字母中删除句点,如果它在 *.bib 文件中。我不知道这是否可行,如果可行,我该怎么做。

答案1

格式化文件内的名称列表的函数bst名为format.names。例如,对于文件apa.bst,此函数具有以下代码:

FUNCTION {format.names}
{ 's :=
  #1 'nameptr :=
  s num.names$ 'numnames :=
  numnames 'namesleft :=
    { namesleft #0 > }
    { s nameptr "{vv~}{ll}{, jj}{, f.}" format.name$ 't :=   % last name first
      nameptr #1 >
  [... etc ...]
}

有关文件和此功能中使用的语法的详细信息bst,请参阅文档驯服野兽(第 35 页)。

在这种情况下,我们必须修改的行是包含该字符串的行:

"{vv~}{ll}{, jj}{, f.}"

此字符串指定每个作者姓名所需的格式。vv表示“von”部分(如果存在)ll是完整的姓氏,jj表示“junior”部分(如果存在),最后ff是完整的名字,而f表示名字的首字母。逗号和点是文字,并添加到输出中。

删除后面的点f即可得到您想要的结果,或者几乎是您想要的结果:

几乎

请注意,由于我们使用了f而不是ff,所以名字和中间名都是缩写。但是使用 时,ff我们将两者都展开。显然,BibTeX 没有“中间名”的概念,所有不是姓氏的都被视为名字。

如果您需要“完全展开”的第一个名字,但中间名缩写且不带点,那么这超出了我的 bibtex 能力。我甚至不知道这是否可行。

答案2

我向同事展示了我最初的答案(如下),他发现了一个病态案例。我应该指出,我们的特定应用首先是针对缩写的中间名(与 OP 询问的不完全相同,但是是一种很常见的需求)。

他对我说:“你知道,有一个简单的方法可以解决这个问题。”编辑解析名称的 .bst 文件(它看起来像nameptr "{ff~}{vv~}{ll}{, jj}"),并将名字字段(带有f)更改为{f{}~}(或者{f{}}如果它是作者字段中出现的最后一项)。

那有多容易?! 它对我们的应用程序来说非常有效。虽然它不完全是 OP 的查询,但我认为它非常有用,我想将其列在网站上,以便其他需要定制作者字段的人使用。

更新:我后来得知,这个技巧是由 Oren Patashnik 在他的文档“BibTeXing”的最后一段中提供的,可以在以下网址找到:http://bibtexml.sourceforge.net/btxdoc.pdf

更改 plain.bst 中的那一行会产生以下 MWE(与我的原始答案相同):

\documentclass{article}
\usepackage{filecontents}
\begin{filecontents}{mybib.bib}
@BOOK{author1999book,
title = {Very Informative and Handsome Book},
publisher = {College Town, ST: College University Press},
year = {1999},
author = {First M. Last},
}
@BOOK{test2,
title = {Very Informative and Handsome Book},
publisher = {College Town, ST: College University Press},
year = {1999},
author = {Last, First M.},
}
@BOOK{test3,
title = {Very Informative and Handsome Book},
publisher = {College Town, ST: College University Press},
year = {1999},
author = {Last, F. M.},
}
\end{filecontents}
\bibliographystyle{plain}

%%BibTeX Dot Removal Macro
\let\svdot. % CAN SAVE THE DOT IF NEEDED SOMEWHERE IN AUTHOR LIST
\catcode`.=\active
\def\NoBibDots#1{\let.\relax#1\catcode`.=12}
% THE FOLLOWING LINE WOULD BE USEFUL FOR "Last FM, ..." FORMATS
%\def\NoBibDots#1{\def~{ }\let.\ignorespaces#1\catcode`.=12}
\catcode`.=12
\begin{document}
Citing\cite{author1999book,test2,test3}
\bibliography{mybib}
\end{document}

产生此输出

在此处输入图片描述

原始答案:

我对这个问题思考了一段时间(自去年 7 月以来),试图解析作者以删除点,但遇到了一些小问题和怪癖。但后来我想到了一个不同的想法,即.激活删除点。它实际上会从作者列表中删除每个点(可以通过\svdot{}在 bib 条目中使用来撤销)。

在本 MWE 中,我使用了 plain.bst,但已验证该方法适用于其他配置(可能需要进行一些调整)。我提供了注释代码,用于使用方法的 bst 文件LAST FM(请参阅apalike本文末尾的示例)。要准备 bst 文件,请添加此宏:

FUNCTION {no.bib.dots}
{ duplicate$ empty$
    { pop$ "" }
    { "\catcode`.=\active\NoBibDots{" swap$ * "}\catcode`.=12" * }
  if$
}

并修改此标准:

FUNCTION {format.authors}
{ author empty$
    { "" }
%    { author format.names }% THIS WAS THE ORIGINAL LINE REPLACED BELOW
     { author format.names no.bib.dots "." * }
  if$
}

注意

{ author format.names no.bib.dots "." * }

可以替换为

{ author format.names no.bib.dots "~" * }

如果你想要一个尾随空格而不是句点,或者简单地使用

{ author format.names no.bib.dots }

既不包含空格也不包含句号。然后,在您的文档、样式或类中,定义\NoBibDots如下:

%%BibTeX Dot Removal Macro
\let\svdot. % CAN SAVE THE DOT IF NEEDED SOMEWHERE IN AUTHOR LIST
\catcode`.=\active
\def\NoBibDots#1{\let.\relax#1\catcode`.=12}
% THE FOLLOWING LINE WOULD BE USEFUL FOR "Last FM, ..." FORMATS
%\def\NoBibDots#1{\def~{ }\let.\ignorespaces#1\catcode`.=12}
\catcode`.=12

以下是完整的 MWE 和相关结果:

\documentclass{article}
\usepackage{filecontents}
\begin{filecontents}{mybib.bib}
@BOOK{author1999book,
title = {Very Informative and Handsome Book},
publisher = {College Town, ST: College University Press},
year = {1999},
author = {First M. Last},
}
@BOOK{test2,
title = {Very Informative and Handsome Book},
publisher = {College Town, ST: College University Press},
year = {1999},
author = {Last, First M.},
}
@BOOK{test3,
title = {Very Informative and Handsome Book},
publisher = {College Town, ST: College University Press},
year = {1999},
author = {Last, F. M.},
}
\end{filecontents}
\bibliographystyle{plain}

%%BibTeX Dot Removal Macro
\let\svdot. % CAN SAVE THE DOT IF NEEDED SOMEWHERE IN AUTHOR LIST
\catcode`.=\active
\def\NoBibDots#1{\let.\relax#1\catcode`.=12}
% THE FOLLOWING LINE WOULD BE USEFUL FOR "Last FM, ..." FORMATS
%\def\NoBibDots#1{\def~{ }\let.\ignorespaces#1\catcode`.=12}
\catcode`.=12
\begin{document}
Citing\cite{author1999book,test2,test3}
\bibliography{mybib}
\end{document}

在此处输入图片描述


为了演示其他 bst 样式的灵活性,我对 apalike.bst 进行了与上述 plain.bst 相同的更改。 apalike具有“Last, FM”格式,我想将其表示为“Last, FM。”。以下 MWE 中,我重新定义\NoBibDots为在删除点后吸收空格,给出了相关结果:

\documentclass{article}
\usepackage{filecontents}
\begin{filecontents}{junk.bib}
@ARTICLE{bake67,
        TITLE   = "Prediction and scaling of reflected impulse from
                        strong blast waves",
        AUTHOR  = "Baker, W. E.",
        JOURNAL = "International Journal of Mechanical Sciences",
        VOLUME  = "9",
        NUMBER  = "1",
        PAGES   = "45--51",
        YEAR    = "1967"                        }
@ARTICLE{Acme72,
        TITLE   = "Prediction and scaling of reflected impulse from
                        strong blast waves",
        AUTHOR  = "Acme, Wesley E.",
        JOURNAL = "International Journal of Mechanical Sciences",
        VOLUME  = "9",
        NUMBER  = "1",
        PAGES   = "45--51",
        YEAR    = "1972"                        }
@ARTICLE{cake71,
        TITLE   = "Prediction and scaling of reflected impulse from
                        strong blast waves",
        AUTHOR  = "Cake, Wesley Excaliber",
        JOURNAL = "International Journal of Mechanical Sciences",
        VOLUME  = "9",
        NUMBER  = "1",
        PAGES   = "45--51",
        YEAR    = "1971"                        }
@ARTICLE{Delta71,
        TITLE   = "Prediction and scaling of reflected impulse from
                        strong blast waves",
        AUTHOR  = "Delta, W. Excaliber",
        JOURNAL = "International Journal of Mechanical Sciences",
        VOLUME  = "9",
        NUMBER  = "1",
        PAGES   = "45--51",
        YEAR    = "1971"                        }
\end{filecontents}
%%BibTeX Dot Removal Macro
\let\svdot. % CAN SAVE THE DOT IF NEEDED SOMEWHERE IN AUTHOR LIST
\catcode`.=\active
%\def\NoBibDots#1{\let.\relax#1\catcode`.=12}
% THE FOLLOWING LINE WOULD BE USEFUL FOR "Last FM, ..." FORMATS
\def\NoBibDots#1{\def~{ }\let.\ignorespaces#1\catcode`.=12}
\catcode`.=12
\begin{document}
cite \cite{bake67, Acme72, cake71, Delta71}
\bibliographystyle{apalike}
\bibliography{junk}
\end{document}

在此处输入图片描述

答案3

在深入研究bst语法之后,我终于能够编写解决方案。我的“简单破解”结果并不那么简单,所以我认为它值得一个新的详细答案。

我的想法是使用format.name$具有格式的函数"{ff}"仅提取名字(在您的示例中为“First Medium”),然后再次使用format.name$此结果,并使用字符串"{ff}{ l}"根据需要获取“First M”。

但后来我尝试涵盖这种简单黑客攻击会失败的其他可能性,例如作者没有中间名,甚至没有名字(仅提供姓氏)。由于检测和处理此类情况的代码开始变得过于复杂,我编写了一个特定函数来完成所有这些工作,然后从主格式化作者函数中调用该函数。

调用新函数format.trick,并期望堆栈顶部有一个包含单个作者姓名的字符串(例如“First Medium Last”,也接受符号“Last, First Medium”。此函数在堆栈顶部留下“规范化”名称,即“Last, First M”。它可以正确处理没有媒介名称或没有名字的作者。这是此函数的大量注释代码:

STRINGS {ss tt fm}
FUNCTION {format.trick}
{
    'ss :=   %% Make a copy of the name in s
    %% Extract the First (and possible Medium) names
    %% and store it in variable fm
    ss #1 "{ff}" format.name$ 'fm :=

    %% Note that now fm could contain:
    %% * An empty string ("") if the author has no first name (only Last name was provided)
    %% * A single word (like "First") if the author has no medium name
    %% * A sequence of words (like "First Medium")
    %% For the last case we want to abbreviate "Medium", without dot

    %% Test if we are in the first case
    fm empty$ {
       % If empty (no first name), use the standard formatting
       ss #1 "{vv~}{ll}{, jj}{, ff}" format.name$
    }{ % Otherwise, attempt the trick
        %% Now the trick. Interpret "First Medium"
        %% as if "Medium" were a last name, and abbreviate it
        fm #1 "{ff }{l}" format.name$ 'tt :=   %% And store the result in tt
        %% Consider the particular case in which no Medium name is present
        %% In this case, "First" will be interpreted as a last name, and
        %% thus abbreviated. This can be detected because the resulting
        %% string has length 1
        tt text.length$ #1 > { %% If there was a medium name
            tt  %% Store the abbreviated version
            }{  %% Else store the original version of the name
            fm
            } if$

        %% After the above, the top of the stack will contain
        %% either "First" unabbreviated (if the author has not middle name)
        %% or "First M", as required
        'tt :=  %% Copy that value to tt

        %% Now complete the standard formatting of the author, omitting
        %% the first name part, which is stored in tt
        ss #1 "{vv~}{ll}{, jj}" format.name$
        %% And concatenate to it the value of tt
        ", " *
        tt *
  }if$   %% If the trick has to be done
}

您可以在函数bst之前的任何位置插入该代码format.names,然后修改format.names函数,更改以下行:

    { s nameptr "{vv~}{ll}{, jj}{, ff}" format.name$ 't :=

    { s nameptr "{vv~}{ll}{, jj}{, f}" format.name$
      % Postprocess result
      format.trick 't :=

我尝试了新的包含复杂作者列表的.bst方法:bib

@BOOK{author1999book,
    title = {Very Informative and Handsome Book},
    publisher = {College Town, ST: College University Press},
    year = {1999},
    author = {
          Last, First Middle
      and Lastonly
      and Last2, First2 M.
      and Last3, First3 M
      and Last4, Firstonly
    }
}

它按预期工作:

结果

理解基于堆栈的 bst 语言很有趣。:-)

更新

OP 使用的bst风格稍微复杂一些,其中第一位作者的格式与其余作者不同。这使得我的上述技巧无法直接使用。OP 为我提供了完整的内容bst,我能够找到需要修改哪些行以适应上述技巧。

函数format.authorsformat.rem.authors(分别生成第一作者和其余作者的格式)必须像这样修改(虽然只需要更改两行,但我更喜欢粘贴完整的函数):

FUNCTION {format.rem.names}
{ 's :=
  'f :=
  #2 'nameptr :=
  s num.names$ 'numnames :=
  numnames #1 - 'namesleft :=
    { namesleft #0 > }
    { s nameptr f format.name$   % <-----
      format.trick               % <-----
      #1 f format.name$ 't :=    % <-----
      nameptr #1 >
    { namesleft #1 >
        { "; " * t * }
        { t "others" =
        { " et~al." * }
        { "  \& " * t * }
          if$
        }
      if$
    }
    't
      if$
      nameptr #1 + 'nameptr :=
      namesleft #1 - 'namesleft :=
    }
  while$
}

FUNCTION {format.authors}
{ author empty$
    { "" }
    { author #1 "{vv~}{ll}{, jj}{, ff}" format.name$
      format.trick                                     %% <----
      #1 "{vv~}{ll}{, jj}{, ff}" format.name$          %% <----
      "{ff }{vv~}{ll}{, jj}" author format.rem.names
    }
  if$
}

该函数的代码format.trick与我在上面的原始答案中给出的代码相同。

经过这些更改后,参考书目条目如下所示:

结果

请注意,第一作者是“姓,名”,而其余作者是“名,姓”,并且在所有情况下,中间名都缩写而不带点。我猜这是所需的输出。

相关内容