多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

LaTeX中文参考文献“et al”难题与上标设置全解

LaTeX中文参考文献“et al”难题与上标设置全解 写毕业论文那阵子我被同一个问题折磨了好几个晚上参考文献明明都整理在 bib 文件里了编译出来的效果却总是不对劲。最典型的就是中文文献的几位作者名字明明是“陈某某、李某某、王某某、赵某某”编译出来的参考文献列表却给你整一句“陈某某 et al.”。中文论文里到处冒出英文“et al.”这画面你想象一下就知道有多违和。和“et al.”同样让人焦虑的还有参考文献编号到底该上标还是不该上标——不同学校、不同期刊的要求五花八门改来改去永远差一点。这篇内容我就把这两件事合并起来讲清楚先解决中文文献“et al”问题的根源再给出上标和不上标的完整设置方案最后附上我踩过的坑和排查清单。1. 先说痛点中文文献里的“et al”是怎么来的1.1 BibTeX 工作流程还原bib 文件是原材料但它本身不会直接决定参考文献列表长什么样真正做格式化的是 bst 样式文件。整个链条是这样的在 tex 里写\cite{key}第一次编译 xelatexLaTeX 会在.aux文件里记录下所有被引用的 keybibtex 程序读取.aux再根据\bibliographystyle指定的.bst规则去.bib里找对应条目生成.bbl文件第二次编译 xelatex.bbl内容被嵌入正文如果有交叉引用、页码目录还要再跑一两次 xelatex。这五步看起来简单但第 3 步经常被人忽略。你以为参考文献列表的样式是你自己控制的其实不是是.bst在控制。.bst决定作者列表怎么缩写、名字怎么排、期刊名要不要缩写、年份放哪、以及最主要的——超过几个人之后用省略词省略词用“et al”还是“等”。默认的plain.bst、unsrt.bst都是英文世界的产物它内置的省略词就是et al.也不会去判断文献是中文还是英文。所以只要你还在用这些默认 bst中文文献里的“et al”就永远消不掉。1.2 为什么不能直接改 bst 了事有些朋友可能想那我干脆把 bst 里的“et al”字符串直接替换成“等”不就行了想法很直接但落地会翻车。原因很简单bst 服务的是整篇文档的全部引用英文文献和中文文献用同一个规则。你要是把字符串一换英文文献的省略也变成了“等”。这比保留“et al”还糟糕——英文文献列表里冒中文一样是格式事故。正确的思路是让格式化工具有语言判断能力。中文文献按国标显示“等”英文文献按国际惯例显示“et al.”。这就不是找一个字符串替换能解决的得用专门的宏包或样式。市面上的方案里最主流的是 gbt7714 宏包体系以及 natbib 配合 gbt7714nat 样式。后面我会把两条路都演示一遍。1.3 三个关键变量先记住踩过这一圈的坑后我把问题收敛成三个变量以后遇到任何参考文献显示不对优先检查这三个地方编译引擎中文文献几乎都必须用 xelatex配合 ctex 或 xeCJKpdflatex 对中文字体的支持太折腾宏包选项上标还是不上标是super还是numbers这类宏包选项决定的改正文内容没有用数据源字段bib 条目的language字段是不是chinese直接决定 bst 有没有把这条文献当作中文来处理。这三个变量正好对应了这篇文章的三个核心维度。后面每讲一个方案我都会用这三个变量去校准你跑完代码后也可以自己反复检查。2. 方案一gbt7714 宏包国标格式的开箱即用方案2.1 gbt7714 宏包能解决什么gbt7714 宏包是 CTAN 上专门针对国家标准《GB/T 7714-2015 信息与文献 参考文献著录规则》做的中文文献格式化方案。它有两个核心组件一个是gbt7714.sty管正文里的引用样式另一个是gbt7714.bst管文末参考文献列表的格式化。两者配合作者超过一定数量时中文文献自动跟“等”英文文献自动跟“et al.”国标要求的标点、缩进、作者姓名格式、日期格式等都一并处理到位。套用上一节说的三个变量gbt7714 相当于一次性锁定“中文国标格式”这个大前提编译引擎建议 xelatex宏包选项决定上下标数据源字段决定等/et al 判断。它最大的价值就是让你不用去读一厚本国标原文也不用手动调几十处格式细节。对于写毕业论文、投国内核心期刊的用户来说这是我见过的性价比最高的方案。2.2 安装检查和基本配置新版的 TeX Live 和 MacTeX 其实都已经内置了 gbt7714不需要手动安装。但老旧的 CTeX 套装、定制化精简发行版就未必。你可以先检查kpsewhich gbt7714.sty kpsewhich gbt7714.bst有输出说明已经就位没有任何输出就得补装。TeX Live 用户直接跑tlmgr install gbt7714手动下载也行——把.sty文件和.bst文件放到~/texmf/tex/latex/gbt7714/和~/texmf/bibtex/bst/gbt7714/这样的本地目录然后执行texhash更新数据库。注意 bash 命令只是示意Windows 下请用相应路径。基本配置代码\usepackage[super]{gbt7714} % 上标引用不想上标就改为 numbers \bibliographystyle{gbt7714} \bibliography{refs}这里有个容易踩的点\bibliographystyle{gbt7714}是独立命令而且必须写在\bibliography之前。不要把它当作宏包选项也不要放错位置。有初学者在导言区写\usepackage[gbt7714]{...}这不对——那是在加载宏包不是在设置 bib 样式。2.3 bib 条目的 language 字段是命门这是整个方案里最容易被忽略、也是失败率最高的一个点。gbt7714.bst 判断一条文献该用“等”还是“et al.”核心依据就是 bib 条目里的语言字段。如果你的 bib 条目是从百度学术、CNKI、Google Scholar 直接导出粘贴的很多情况下并没有language {chinese}或者被写成了别的形式。那 bst 就会按默认的英文逻辑走继续输出“et al.”。正确的中文文献条目至少长这样article{chen2023, author {陈某某 and 李某某 and 王某某 and 张某某 and 赵某某}, title {某中文论文标题}, journal {某中文期刊}, year {2023}, volume {45}, number {2}, pages {101--110}, language {chinese} }注意两点。第一language {chinese}是必须加的英文文献可以写language {english}不写默认按英文处理。第二不同工具导出的字段名不一样可能是langid、lang但 gbt7714 的 bst 主要识别language。导入后最好打开.bib文件全局搜索一遍确认字段风格统一。如果 gbt7714 宏包装好了、编译顺序也正确中文文献还是固执地显示“et al”90% 是 bib 条目的language字段的问题。先查字段再查别的。2.4 可直接抄走的 MWE 代码我给出一个完整的最简示例你本地建个文件夹把下面两个文件放进去就能跑通。主文件main.tex% !TEX program xelatex \documentclass{ctexart} \usepackage[super]{gbt7714} % 上标引用模式 % \usepackage[numbers,sortcompress]{gbt7714} % 非上标 排序压缩 \begin{document} 正文里引用一下\cite{chen2023} 和 \cite{lu2021,xing2019}。 \bibliographystyle{gbt7714} \bibliography{refs} \end{document}refs.bib里至少要有chen2023这条记录并带上language {chinese}字段。编译时按下面的顺序执行xelatex main bibtex main xelatex main xelatex main如果你用 VSCode LaTeX Workshop可以在 settings.json 里写一个包含这四个步骤的 recipe之后一键编译。关于 VSCode 配置的具体细节我后面在常见问题章节里补充。2.5 为什么编译顺序偏偏要四次很多新手第一次跑 BibTeX会因为“不显示引用”而怀疑人生。其实原因很简单xelatex 第一次编译只能扫描出引用 key生成.auxbibtex 读取.aux后生成.bbl第二次 xelatex 才把.bbl内容真正嵌入 PDF但此时页面可能还没稳定还要第三次 xelatex 把交叉引用、目录、页码全部收敛。如果你只跑一次 xelatexPDF 里自然什么都没有。用编辑器顺手的话直接设置保存后自动跑全流程会比手动敲命令省心很多。注意\bibliographystyle{gbt7714}必须写在\bibliography{refs}之前否则 BibTeX 不会使用它。3. 方案二natbib gbt7714nat灵活引用的进阶组合3.1 natbib 的基本用法如果你需要的不仅仅是国标格式还要在正文里灵活控制引用样式gbt7714 自带的\cite命令就有点不够用了。此时可以引入 natbib 宏包。natbib 是 LaTeX 生态里一个老牌的引用宏包它提供了\citep括号引用、\citet文本引用这两大类命令并且支持作者年份、数字序号、上标等多种模式可控性比原生\cite强得多。基本加载方式\usepackage[numbers,round]{natbib} % 数字引用圆括号包裹 % \usepackage[super]{natbib} % 上标数字引用这里的numbers对应数字序号样式round表示引用编号用圆括号而不是方括号。如果你要用上标直接加载super选项。但先别急着选还有一个关键点natbib 只是个“壳”它真正输出的参考文献列表格式依然由 bst 文件决定。你用 natbib就必须搭配支持 natbib 的 bst比如plainnat、abbrvnat或者中文本土方案gbt7714nat。3.2 自定义上标命令\upcitenatbib 有一个优点你可以不局限于它预设的样式而是基于它的命令去自定义。最常用的自定义就是做“局部上标”。假设你的文档全局是[numbers,round]的非上标模式但图注、表格注、算法说明里需要个别上标。直接改全局选项不划算定义一个新命令才是正解\usepackage[numbers,round,sortcompress]{natbib} % 在不影响 \citep 的前提下新增上标引用命令 \newcommand{\upcite}[1]{\textsuperscript{\citep{#1}}}使用方式正文普通引用 \citep{key1,key2}。 图注中的引用 \upcite{key1}。\textsuperscript会把后面的内容整体抬升成上标。因为\citep输出的是(1,2)这样的数字引用所以上标后效果就是“^(1,2)”该有的括号都在顺序也受sortcompress控制。实测下来这种方案对于期刊排版特别实用编辑部要求图注中引用上标总不能让整篇文档都变上标。你也可以定制无括号的纯上标数字做法是把\citep换成\citealp——\citealp是 natbib 里的“无括号引用”命令\newcommand{\supnum}[1]{\textsuperscript{\citealp{#1}}}输出就是纯上标的数字不带括号。喜欢简洁风格的人可以用这个。3.3 配套 gbt7714nat.bst 解决中文“等”natbib 本身不懂国标所以“et al”问题还得交给懂国标的 bst 来解决。gbt7714 宏包恰好就提供了一个专门面向 natbib 的 bst 文件——gbt7714nat.bst。名字里的 nat 已经说得很明白它就是为了配合 natbib 使用的。配置方式\usepackage[numbers]{natbib} \bibliographystyle{gbt7714nat} \bibliography{refs}注意用了这个组合就不需要再写\usepackage{gbt7714}了避免宏包重复冲突。此时中文文献的“等/et al”判断同样依赖 bib 条目的language {chinese}字段所以第 2.3 节的规范依然适用。这套组合和 gbt7714 相比区别在于gbt7714 给你的是一个完整的、开箱即用的国标体验而 natbibgbt7714nat 则是把引用的控制权交还给你你可以在\citep、\citet和自定义命令之间自由切换。如果你写的是理学、工学的学位论文经常需要在“作者年份”和“数字序号”两种风格之间权衡我建议走 natbib 这条线。3.4 方案选型建议说了这么多直接给你一个选择逻辑用的是学校统一的毕业论文模板模板里已经定了 bst那么优先用 gbt7714需要自己在两种引用风格之间来回切换或者对\citet有刚需那就 natbib gbt7714nat如果编辑部/出版社要求的是国标 GB/T 7714-2015并且你的论文要交给 biblatex biber 做更复杂的数据处理可以研究一下第 4.4 节里的 biblatex 路线如果只是临时改一处两处上标不想动宏包体系那自定义\upcite命令已经足够。这条选择逻辑是我的个人经验不一定适配所有期刊但至少能帮你少走弯路。4. 参考文献上标与不上标全解4.1 全局上标/不上标速查表先说全局设置。不管是 gbt7714 还是 natbib上标/不上标本质都是宏包加载时的选项问题不需要改动正文。把选项理清楚一张表就能说透宏包方案上标引用非上标引用适用场景gbt7714\usepackage[super]{gbt7714}\usepackage[numbers]{gbt7714}中文国标格式、毕业论文明natbib\usepackage[super]{natbib}\usepackage[numbers,round]{natbib}需要\citep/\citet灵活控制纯命令方案\newcommand{\upcite}[1]{\textsuperscript{\cite{#1}}}直接用\cite{key}不新增宏包依赖的临场救急需要澄清一点gbt7714 的numbers选项默认输出方括号数字[1]这是国标顺序编码制的常规面貌。natbib 的numbers选项默认也是方括号如果你想要圆括号(1)才需要加round。上标模式下gbt7714 和 natbib 的输出都是纯上标数字不带括号视觉效果很干净。4.2 局部临时切换上标/不上标我把这一节单拎出来是因为“局部切换”是最高频的真实需求。比如某期刊模板要求正文引用全部用方括号非上标但图表题注里却要求上标。这种情况下全局改一个选项反而会搞乱整篇文档正确做法是局部覆盖。第一个办法自定义命令。\newcommand{\upcite}[1]{\textsuperscript{\citep{#1}}} \newcommand{\normcite}[1]{\citep{#1}}然后在正文里自由切换正文普通位置用 \normcite{key1}。 图注里面用 \upcite{key1}。第二个办法针对单条命令做环境级修改。如果你的某个段落里要全部上标但又不愿破坏全局配置可以用大括号包一层配合\renewcommand覆盖{\renewcommand{\citep}[1]{\textsuperscript{\citealp{#1}}} % 在这里 \citep{...} 全部以上标形式输出 }但说实话第二种方式可读性差维护成本高我实际项目中几乎不用。我自己的习惯是全局保持一个基调凡是个别需要变化的地方一律用自定义命令去写名字取得一眼就能看懂比如\upcite这样全文搜索也很方便。4.3 上标数字的中文字距微调上标数字和中文正文之间的视觉间距经常被忽略。默认情况下上标数字总会紧贴前面的汉字或标点有时候挤得难受有时候又觉得位置飘。我常用的微调手段有两个。一个是在上标数字前加一个细空格\newcommand{\upcite}[1]{\textsuperscript{\,\citep{#1}}}\,会插入一个细空格中文正文里的上标看起来会从容很多。另一个是调节上标本身的垂直位置。极少数情况下你会觉得上标太高或太低这时可以用\raisebox手调\newcommand{\upcite}[1]{\raisebox{0.1ex}{\textsuperscript{\citep{#1}}}}0.1ex可以按自己的观感改成0.2ex或-0.1ex这在字库差异比较大的中文字体下很好用。期刊模板如果已经有严格的排版规定最好先测试一个样本发给编辑部确认别自己调得太欢最后不符合要求被打回。4.4 用 biblatex 的读者看这里如果你用的是 biblatex biber 路线这在很多英文模板和较新的学术期刊模板里已经是主流上下标的处理思路和 BibTeX 不太一样。biblatex 的引用命令\cite在stylenumeric或gb7714-2015这类数字样式下默认输出的是数字序号但并不是上标。想要上标同样可以用自定义命令包装\usepackage[backendbiber,stylegb7714-2015]{biblatex} \addbibresource{refs.bib} \newcommand{\supcite}[1]{\textsuperscript{\cite{#1}}}正文中\cite{key}会生成普通数字引用\supcite{key}则生成上标数字。如果你需要一次引用多个文献并且全部上标可以用\textsuperscript{\cites{key1}{key2}}注意是\cites复数命令。编译流程相应改成 xelatex → biber → xelatex → xelatex因为 biber 取代了 bibtex。这里特别提醒biblatex 的gb7714-2015样式同样解决了中文文献的“等”与“et al”问题它内部已经处理了国标规则。所以如果你是从 biblatex 路线进入这个坑的记住两件事biber 别写错language/langid 字段别丢。5. 常见问题与排查技巧实录5.1 高频问题速查表现象可能原因解决方法中文文献还是显示“et al”bib 条目缺language {chinese}补上字段重新编译全流程英文文献被显示成“等”英文条目被全局替换或语言字段误判给英文条目显式加language {english}PDF 里的引用编号不出现只跑了一次 xelatex.bbl还没生成按 xelatex→bibtex→xelatex→xelatex 顺序跑齐上标数字和正文挤在一起缺少字间距设置用\textsuperscript{\,\citep{#1}}微调多个引用排序混乱没用sort或sortcompress宏包选项加上sortcompress改了 bst 但还是“et al”可能改的是别的文件或没清缓存确认\bibliographystyle{gbt7714}删除.bbl/.aux重编译中文作者名字倒过来bib 条目的 author 写成Last, First格式改成author {张三 and 李四}完整人名这张表虽然不完全但它覆盖了我在实际使用和帮朋友排查文献问题时遇到的大多数场景。如果你的问题不在表里往三个关键变量上靠编译引擎、宏包选项、数据源字段。5.2 五步排查流程照着走就能定位如果你的问题顽固不化建议按下面五个步骤来每一步都能排除一批可能性。第一步确认引擎。中文文献和 ctex 宏包一起使用时基本只能走 xelatex。打开编译日志开头如果是This is pdfTeX先换成 xelatex 再试。第二步确认宏包加载顺序。ctex/xeCJK、natbib、gbt7714 三者顺序别乱。一般顺序中文字体支持 → 引用宏包 → 自定义命令。gbt7714 和 natbib 不建议同时加载除非你明确知道自己在做什么。第三步检查 bib 文件编码。用 VSCode 打开右下角看编码必须是 UTF-8。Windows 记事本默认的 UTF-8 带 BOM有些 BibTeX 版本会报错或识别错误尽量另存为 UTF-8 without BOM。第四步看.bbl文件。打开编译后生成的.bbl搜索et al或等。这里面直接反映 bst 的真实输出。如果.bbl里已经正确显示“等”PDF 里却没变问题在于没重新编译如果.bbl里是“et al”那就回到 language 字段和 bst 名称去检查。第五步清理再编译。经常有旧缓存文件干扰。把.aux、.bbl、.blg、.out这类辅助文件全删掉从头按完整顺序跑一遍编译。这一步能解决很多“莫名其妙”的问题。5.3 批量给 bib 文件补 language 字段最后一个工具型技巧。如果你的 bib 文件里有大量中文文献一条条手动加language字段非常痛苦直接上脚本处理。我展示一个用 Python bibtexparser 批量补字段的方案pip install bibtexparserimport re import bibtexparser from bibtexparser.bparser import BibTexParser from bibtexparser.bwriter import BibTexWriter CJK_RE re.compile(r[\u4e00-\u9fff]) def add_languages(in_file, out_file): with open(in_file, r, encodingutf-8) as f: db bibtexparser.load(f, parserBibTexParser()) changed 0 for entry in db.entries: if language in entry or langid in entry: continue title entry.get(title, ) author entry.get(author, ) if CJK_RE.search(title author): entry[language] chinese changed 1 with open(out_file, w, encodingutf-8) as f: f.write(BibTexWriter().write(db)) print(f补齐 {changed} 条中文文献的 language 字段) add_languages(refs.bib, refs_new.bib)这个脚本有个局限它是靠标题或作者字段里是否含中文字符来推断文献语言万一是翻译成中文标题的英文文献有概率被误判。所以跑完以后一定要随机抽几条人工查验一下毕竟批量修改的错误代价比手动慢几秒要高得多。如果你比较介意可以把title也去掉直接用author字段的 CJK 字符判断误判率会低一点。6. 写在最后我的血泪实操心得6.1 三条路线实测后的最终建议写这篇之前我专门重新搭了一个干净的测试环境把 gbt7714、natbib gbt7714nat、biblatex 三条路线全部实测了一遍确认上面每一个代码片段都能跑通。实测下来我个人最推荐的组合很明确写毕业论文就用 gbt7714 一条路走到黑满足国标也最省心如果你需要在文档中频繁切换引用风格那就换 natbib gbt7714nat并且养成用自定义命令的习惯不要在文档里堆一堆\cite和\citep混着写维护成本太高。6.2 我一直在用的几个小习惯有几个小习惯是我这几年慢慢养成的觉得特别值得分享。第一用一个固定的refs.bib别在多个文件里倒腾。配合 Zotero 的 Better BibTeX 插件自动导出我的入库和维护成本几乎降到零。需要引用某篇文献时直接在 Zotero 里点一下插件会把 key 同步到剪贴板回到 VSCode 里\cite{key}一条龙完成。第二一定要给 tex 文件加% !TEX program xelatex这个魔法注释。VSCode 的 LaTeX Workshop 读取这一行会自动选择合适的编译流程。团队协作时这个注释也能避免别人拿到你的源码后编译报错。第三发生任何诡异问题第一时间把项目里的.aux、.bbl、.blg全删掉重新跑完整流程。这不是玄学而是因为辅助文件里存着上一次编译的缓存经常把老数据带进新结果。我遇到过不止一次一切都改对了但多跑一遍完整编译后问题自己消失了。最后再分享一个小技巧如果你的投稿期刊要求参考文献顺序编码制但正文图表又允许上标不要试图通过改宏包选项去兼容直接定义两个命令一个\upcite一个\normcite在正文里按需调用。这个小技巧在投几个工科期刊时帮我省了很多事。
返回列表