natbib

写出 natbib 的人并不喜欢这个名字。在宏包的带注释源码 natbib.dtx 里,Patrick W. Daly 说明名字来自 Stephen Gildea 的 natsci.bst——natsci 即 natural sciences(自然科学)——并在括号里补了一句:这名字确实难看,但已经通行开来,不好再改。难看归难看,要让 LaTeX 从经典 BibTeX 里排出 (Jones et al., 1990) 这类作者-年份引用,靠的仍然是 \usepackage{natbib}。本页越过 \citet\citep 的语法之别——那属于「引用基础」那一页——直接谈真正让人卡住的地方:哪些 .bst 能配合 natbib、哪些不能,(author?) 究竟在说什么,以及 roundsquare\bibpunct\setcitestyle 之中到底是谁在决定括号。

\usepackage{natbib} 与配套的三种样式:plainnat、abbrvnat、unsrtnat

导言区两行就够了:\usepackage{natbib}\bibliographystyle{plainnat}。第二行比看上去重要得多,写错它正是引用出问题的根源。natbib 自带三个 .bst 文件——plainnatabbrvnatunsrtnat——它们排出的参考文献表与标准的 plainabbrvunsrt 完全一致,只是往每条 \bibitem 里多写了一样东西:分别标注的作者与年份。这个多出来的标签就是全部机关。标准 BibTeX 样式只写 \bibitem{jon90},于是 LaTeX 永远只能印出一个不透明的编号;nat 系列样式写的是 \bibitem[Jones et al.(1990)Jones, Baker, and Williams]{jon90},natbib 便能从这一行按需拼出简写作者名、完整作者名、年份或编号。

运行顺序与纯 BibTeX 无异:latex(或 pdflatex)→ bibtexlatexlatex。第一遍把引用键写进 .auxbibtex 生成 .bbl,最后两遍再把标签读回来。日文文献则用 pbibtex / upbibtex 代替 bibtex。natbib 添加的只有一件事:同一份 .bib、同一个 plainnat,只要你开口,也能排出数字式引用。作者-年份的宏包在 natbib 于 1993 年问世之前早已存在——harvardapalikechicagoastron——但它们每一个都把稿件锁死在一种引用方式上,改投数字式期刊就意味着改写正文。natbib 学会了读懂它们全部的 \bibitem 标签,把引用方式变成了一个宏包选项的问题。

document.tex
\documentclass{article}
\usepackage{natbib}
\bibliographystyle{plainnat}   % not plain: only plainnat carries author and year
\begin{document}

The line-breaking algorithm is described by \citet{knuth1986}.
The same idea is used elsewhere \citep[chap.~2]{lamport1994}.

\bibliography{refs}
\end{document}

% pdflatex doc -> bibtex doc -> pdflatex doc -> pdflatex doc
% (pbibtex or upbibtex instead of bibtex for Japanese references)

引用印成 (author?)Author undefined for citation 是什么意思

这一对——PDF 里那个粗体的 (author?),以及日志里的 Package natbib Warning: Author undefined for citation 'knuth1986' on page 1——意思是你指定的 .bst 做不了作者-年份。\bibliographystyle{plain} 配上 \citet,每次都会得到这个结果:plain.bst 写出的是光秃秃的 \bibitem{knuth1986},natbib 找不到作者,于是 \citet{knuth1986} 退化成 (author?) [1]。麻烦之处在于,同一份文档里的 \citep 看起来完全正常——它只需要编号——所以在长篇草稿里很容易漏掉。修法是改用能携带数据的样式:用 plainnat 代替 plainabbrvnat 代替 abbrvunsrtnat 代替 unsrt,或者选一个 natbib 认得的作者-年份样式(chicagoapalikenamedagsmdcukluwer)。换样式之后要重跑 bibtex;只改 .tex 不会刷新 .bbl 里的标签。

thebibliography
% plain.bst writes this -- no author, no year, so \citet cannot work
\bibitem{jon90}

% plainnat.bst writes this -- short list, year, then the full list
\bibitem[Jones et al.(1990)Jones, Baker, and Williams]{jon90}

% apalike.bst and friends: the minimal form natbib still accepts
\bibitem[Jones et al., 1990]{jon90}

引用命令的整个家族:带星号的 \citet / \citep,以及 \citealt\citealp\citeauthor\citeyear

\citet\citep 之外的命令,全都是为了把一条引用拆成零件。加星号的形式会列出全部作者,而不用「et al.」略去;\citealt\citealp 分别输出与 \citet\citep 相同的内容,但不带括号alt 取自 textual,alp 取自 parenthetical)。\citeauthor 只返回作者名,\citeyear 只返回年份,于是你可以自己拼出「Jones 等人早在 1990 年就主张……」这样的句子。下表的输出来自 \usepackage[round]{natbib}plainnat,键 jon90 代表 Jones, Baker, and Williams (1990)。值得一提的是,\citet 并非一开始就存在:natbib 发布于 1993 年,而 \citet 直到 6.2 版、1996 年 1 月 11 日才加入——这个如今几乎等同于 natbib 的命令,比宏包本身晚了两年多才诞生。

命令输出示例用途
\citet{jon90}Jones et al. (1990)文本式;作者成为句子的一部分
\citep{jon90}(Jones et al., 1990)括号式;整条引用放进括号
\citet*{jon90}Jones, Baker, and Williams (1990)不省略作者,全部列出(文本式)
\citep*{jon90}(Jones, Baker, and Williams, 1990)同样列出全部作者(括号式)
\citealt{jon90}Jones et al. 1990去掉括号的 \citet
\citealp{jon90}Jones et al., 1990去掉括号的 \citep;便于放进自己写的括号
\citeauthor{jon90}Jones et al.只要作者名
\citeauthor*{jon90}Jones, Baker, and Williams只要完整的作者名单
\citefullauthor{jon90}Jones, Baker, and Williams\citeauthor* 相同;较早的写法
\citeyear{jon90}1990只要年份
\citeyearpar{jon90}(1990)把年份放进括号,用在已经写出作者名的句子后
\citetext{priv.\ comm.}(priv. comm.)在引用括号内放入自由文字
\citenum{jon90}21光秃秃的编号,不带括号也不上标

每个 \cite… 命令都接受同样的方括号附注,但 Daly 自己的手册说得很清楚:附注是为 \citep 准备的。给 \citeyear\citeauthor 加附注不会报错,但在数字模式下会被默默忽略,在作者-年份模式下也只接受后置附注。往 \citet 里塞多个键同样被标为「不建议」:带附注时,前置附注会在每个年份前重复,后置附注却只挂在最后一个上;Daly 称这些是「承认的 bug,但这项功能的用处存疑,不值得花力气去修」。实用上,把多篇文献交给 \citep\citet 一次只用一篇。同一作者同一年的多篇文献会自动合并为 (Jones et al., 1990a,b)

latex
The algorithm is due to \citet{knuth1986}.
It runs in linear time \citep[Theorem~3]{knuth1986}.
See the discussion of line breaking \citep[see][chap.~2]{knuth1986}.
Similar ideas appear elsewhere \citep{knuth1986,lamport1994}.
Both papers agree \citep{jon90a,jon90b}.   % -> (Jones et al., 1990a,b)

% author and year taken apart by hand
\citeauthor{jon90} first made the claim in \citeyear{jon90}.

\Citet\Citep:让句首的「della」「van der」大写

用首字母大写的 \Citet\Citep\Citealt\Citealp\Citeauthor(也有带星号的版本)。需要它们的场合是姓氏带有「von 部分」——della Robbia 里的 dellavan der Waals 里的 van der。句中用小写才对,所以 \citet{dRob98} 排出的是 della Robbia (1998);但若以这个名字开启一句话,开头就必须大写。natbib 并不改写 .bib 里的姓氏,只把输出的第一个字母改为大写,因此同一篇文献既可出现在句中也可出现在句首,而参考文献表里的拼写始终只有一种。

命令输出
\citet{dRob98}della Robbia (1998)
\Citet{dRob98}Della Robbia (1998)
\Citep{dRob98}(Della Robbia, 1998)
\Citealt{dRob98}Della Robbia 1998
\Citealp{dRob98}Della Robbia, 1998
\Citeauthor{dRob98}Della Robbia

不动正文一个字,切换到数字式或上标:numberssupersort&compress

只需改动选项里的一个词。写成 \usepackage[numbers]{natbib}\citet{jon90} 就变成 Jones et al. [21]\citep{jon90} 变成 [21],带附注的 \citep[chap.~2]{jon90} 变成 [21, chap. 2]。若写 \usepackage[super]{natbib},得到的是 Nature 一系所用的上标数字。正文里的 \citet\citep 原封不动——这正是 Daly 写 natbib 的理由:设计目标就是让改投期刊只需改导言区的一行,别的什么都不用动。参考文献表的体例由 .bst 决定,因此可以保留 plainnat 而让引用变成数字式。

切到数字式后,三个与排序、压缩有关的选项开始起作用。sort 把多重引用整理成参考文献表的顺序,compress 把连续编号合并为区间,sort&compress 两件事都做——这就是 \citep{a,b,c}[21, 19, 20] 变成 [19–21] 的原因。有两点要留意。在这里往 \citet 里塞多个键比在作者-年份模式下更没有意义,因为得到的只是一串编号前面挂着作者名。另外,在 super 模式下 \citeyearpar 的行为与 \citeyear 完全相同,括号会消失;若某刊物要给上标加括号((Ref. 21) 那种形式),就得用 \setcitestyle{open={(},close={)}} 显式给出括号。还有一个命令会悄悄推翻本节的承诺:光秃秃的 \cite 在作者-年份模式下等同于 \citet,在数字式与上标模式下却等同于 \citep,于是围绕它写成的句子,一旦切换模式就变了语法角色。用 natbib 就写 \citet\citep,别写 \cite

latex
% author-year, the mode the nat styles assume
\usepackage{natbib}

% numeric, sorted, consecutive runs folded into ranges: [19-21]
\usepackage[numbers,sort&compress]{natbib}

% superscript numbers, as used by Nature and its relatives
\usepackage[super,sort&compress]{natbib}

% the body text is identical in all three cases

为什么 plainnat 印出的是 [Jones et al., 1990]roundsquare\bibpunct\setcitestyle

因为 \bibliographystyle{plainnat} 会调用 natbib 内部的 \bibstyle@plainnat,而后者被定义为 \bibpunct{[}{]}{,}{a}{,}{,}。natbib 内建了一张按 .bst 名字索引的标点对照表——chicago 用圆括号加分号,agu 用方括号,nature 用无括号的上标——而 plainnatabbrvnatunsrtnat 都被指定为方括号加逗号分隔。常见的说法是「natbib 默认圆括号」,但这个默认值只有在使用不在 natbib 表内.bst 时才看得见。反过来,只要显式给出任何一个括号、分隔符或模式选项,natbib 就会执行内部的 nobibstyle,关掉由 .bst 驱动的标点设置。所以写 \usepackage[round]{natbib} 即便配 plainnat 也会回到圆括号,而 \usepackage[authoryear]{natbib} 则是特意把这套机制重新打开。

选项效果
round圆括号 (…);当 .bst 名不在 natbib 表内时的默认值
square方括号 […]
curly花括号 {…}
angle尖括号 <…>
semicolon多重引用之间用分号分隔
colonsemicolon 完全相同;这是起错名字的旧选项,8.0 才补上正确拼法
comma多重引用之间用逗号分隔
authoryear作者-年份模式;同时把由 .bst 决定的标点重新打开
numbers数字模式;内部同时执行 squarecomma
super上标数字,括号置空(Nature 一系的做法)
sort把多重引用整理成参考文献表的顺序
compress不排序,只把连续编号折成区间
sort&compress先排序再折成区间,得到 [19–21] 的形式
longnamesfirst每篇文献首次引用列全部作者,之后用 et al.
sectionbibchapterbib 同用,把参考文献表排成 \section*
merge把带 * 的键合并到同一个编号下;相当于 mcite 的功能

若要在宏包载入之后再改体例,就用 \setcitestyle{…}(natbib 8.0、2007 年加入)。它接受一串以逗号分隔的关键字:模式为 authoryear / numbers / super,括号为 round / square / curly / angle,分隔符为 semicolon / comma。更细的控制通过 key={value} 给出——open={(}close={)} 指定括号本身,citesep={;} 指定多重引用之间的分隔,aysep={,} 指定作者与年份之间,yysep={,} 指定年份与年份之间,notesep={, } 指定附注之前。于是写成 \setcitestyle{square,aysep={},yysep={;}},就正好对应「方括号、作者与年份之间不加逗号、年份之间用分号」这样的投稿规定。

preamble
\usepackage[round,semicolon]{natbib}   % (Jones et al., 1990; Smith, 1989)
\bibliographystyle{plainnat}

% change it again, later in the preamble (natbib 8.0 and later)
\setcitestyle{square,aysep={},yysep={;}}

% the older equivalent: [notesep]{open}{close}{citesep}{mode}{aysep}{yysep}
% mode: n = numeric, s = superscript, anything else = author-year
\bibpunct[, ]{(}{)}{;}{a}{,}{,}

\bibpunct 是做同一件事的旧命令,接受一个可选参数加六个必需参数:依次是开括号、闭括号、多重引用之间的分隔符、模式(n 为数字式,s 为上标,其他一律作者-年份)、作者与年份之间的标点、同一作者各年份之间的标点。开头那个可选参数是紧挨附注之前的字符串,默认为 , 。就可读性而言 \setcitestyle 更胜一筹,新文档用它即可,\bibpunct 则只需在旧稿或类文件里遇到时看得懂。也可以只借用某个已知 .bst 的标点,写 \citestyle{chicago} 即可;若想给自制的 .bst 绑定标点,把 \newcommand{\bibstyle@mystyle}{\bibpunct…} 写进 natbib.cfg,此后 \bibliographystyle{mystyle} 就会自动套用。

文档类替你载入 natbib 时:elsarticle 的 nonatbib,以及绝不能再加的 cite 宏包

如果你从没写过 \usepackage{natbib}\citet 却能用,那就是文档类替你载入了。Elsevier 的 elsarticle 会执行 \RequirePackage[\@biboptions]{natbib},并特意提供 \documentclass[nonatbib]{elsarticle} 让你能把它关掉。美国物理学会的 revtex4-2 则写作 \RequirePackage[sort&compress]{natbib},连最低版本都指定了。TeX Live 2024 里有 92 个类文件提到 natbib,Daly 自己也写道,它「被许多期刊支持(乃至要求)」。由此带来一个陷阱:为了整理编号而加上 \usepackage{cite},会得到 Package natbib Warning: The 'cite' package should not be used with natbib. Use option 'sort' insteadcite 的替代是 sortsort&compressmcite 的替代是 mergeelide 选项。另外 citeref 必须在 natbib 之后载入,否则会报错。

现在该选 natbib 还是转向 biblatex

若投稿规定点名了某个 .bst,就用 natbib;若是新文档且可以自由选择,biblatex 更值得考虑。natbib 的长处在于既有的 .bib 文件、.bst 样式和 bibtex 程序都能原样继续用,而且如前所述,大量期刊文档类默认它存在。biblatex(配合负责排序的 biber 后端)把排序与格式都放到 LaTeX 一侧控制,从设计之初就考虑了多语言与本地化输出。natbib 本身自 2010 年的 8.31b 起便不再更新;其中 mergeelide 的代码由美国物理学会委托 Arthur Ogawa 编写——版本字符串里的 (PWD, AO) 正是两位作者的首字母。两者不能并用,只能择一。命令的对应关系(\citet\textcite\citep\parencite)见「引用基础」一页,biblatex 一侧的细节见 biber / biblatex 页。