我在报告文档类中使用 natbib 和“apacite”书目样式。我可以轻松进行多次引用。例如:
\citep{hilary2019, james2013}
给我:
(Hilary et al., 2019; D. A. James, 2013)
我的问题:我的文档中有很多类似上述的多重引用,我想按日期排序(从最旧到最新)。我不是在谈论实际的参考书目,我指的是上面的例子。例如,上面的内容变成:
\citep{hilary2019,james2013}
应该给我:
(D. A. James, 2013; Hilary et al., 2019)
有没有办法让这个过程自动化?我不用再逐条检查命令并排序引用。
任何帮助都非常感谢。谢谢!
答案1
natbib
有一个sort
选项允许您按照条目在参考书目中出现的顺序进行排序\citep
/调用。\citet
\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{babel}
\usepackage{csquotes}
\usepackage[sort]{natbib}
\bibliographystyle{plainnat}
\begin{filecontents}{\jobname.bib}
@book{aardvark,
author = {Anne Aardvark},
title = {Ardvarking},
year = {2020},
}
@book{zebra,
author = {Zoe Zebra},
title = {Zebraing},
year = {2010},
}
\end{filecontents}
\begin{document}
\citep{zebra,aardvark}
\citep{aardvark,zebra}
\bibliography{\jobname}
\end{document}
如果你想以不同于参考书目的方式对引文进行排序,则需要做一些额外的工作。我已经apalike
在文内引用按照出版年份排序,采用类似阿帕网书目格式。
首先,我们需要修改文件.bst
,以便与我们共享预期的引用排序顺序。可以通过添加
FUNCTION {sort.again}
{
year field.or.null sortify
" "
*
sort.label
*
'sort.key$ :=
}
ITERATE {sort.again}
SORT
EXECUTE {newline$}
FUNCTION {produce.sortlist}
{
"\sortentry{"
cite$
*
"}"
*
write$
newline$
}
ITERATE {produce.sortlist}
到文件重命名副本的末尾.bst
。
修改plainnat.bst
后的plainnat-sortcites.bst
样子https://gist.github.com/moewew/783c43bd536de4198d5f5166c886fb61. 具体细节可能因风格不同而有所差异。
然后我们需要文档级代码来从.bbl
文件中提取排序信息并使用它进行排序。以下代码只是对 中的代码进行了轻微修改natbib.sty
。
\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{babel}
\usepackage{csquotes}
\usepackage[sort]{natbib}
\bibliographystyle{plainnat-sortcites}
\usepackage{etoolbox}
\makeatletter
\newcommand*{\sortentry}[1]{%
\if@filesw
\immediate\write\@auxout{\string\scNAT@aux@sortentry{#1}}%
\fi}
\newcommand*{\scNAT@aux@sortentry}{%
\listgadd{\scNAT@bibsortlist}}
\newcommand*{\scNAT@bibsortlist}{}
\newcommand*{\scNAT@citekeys}{}
\newcommand*{\scNAT@writetocitelistsort}[1]{%
\ifinlist{#1}{\scNAT@citekeys}
{\ifdefvoid{\NAT@cite@list}
{\def\NAT@cite@list{#1}}
{\expandafter\def\expandafter\NAT@cite@list\expandafter{\NAT@cite@list,#1}}%
\listgadd{\scNAT@foundkeys}{#1}}
{}}
% Let's be paranoid: we might have dropped an item that
% has not made it to the bibliography yet
\newcommand*{\scNAT@writetocitelistforgotten}[1]{%
\ifinlist{#1}{\scNAT@foundkeys}
{}
{\ifdefvoid{\NAT@cite@list}
{\def\NAT@cite@list{#1}}
{\expandafter\def\expandafter\NAT@cite@list\expandafter{\NAT@cite@list,#1}}}}
\newcommand*{\scNAT@sortcites}[1]{%
\let\NAT@cite@list\@empty
\let\scNAT@citekeys\@empty
\let\scNAT@foundkeys\@empty
\forcsvlist{\listadd{\scNAT@citekeys}}{#1}%
\forlistloop{\scNAT@writetocitelistsort}{\scNAT@bibsortlist}%
\forlistloop{\scNAT@writetocitelistforgotten}{\scNAT@citekeys}%
}
\def\NAT@citex%
[#1][#2]#3{%
\NAT@reset@parser
\NAT@sort@cites{#3}%
\scNAT@sortcites{#3}%<- this is new
\NAT@reset@citea
\@cite{\let\NAT@nm\@empty\let\NAT@year\@empty
\@for\@citeb:=\NAT@cite@list\do
{\@safe@activestrue
\edef\@citeb{\expandafter\@firstofone\@citeb\@empty}%
\@safe@activesfalse
\@ifundefined{b@\@citeb\@extra@b@citeb}{\@citea%
{\reset@font\bfseries ?}\NAT@citeundefined
\PackageWarning{natbib}%
{Citation `\@citeb' on page \thepage \space undefined}\def\NAT@date{}}%
{\let\NAT@last@nm=\NAT@nm\let\NAT@last@yr=\NAT@year
\NAT@parse{\@citeb}%
\ifNAT@longnames\@ifundefined{bv@\@citeb\@extra@b@citeb}{%
\let\NAT@name=\NAT@all@names
\global\@namedef{bv@\@citeb\@extra@b@citeb}{}}{}%
\fi
\ifNAT@full\let\NAT@nm\NAT@all@names\else
\let\NAT@nm\NAT@name\fi
\ifNAT@swa\ifcase\NAT@ctype
\if\relax\NAT@date\relax
\@citea\NAT@hyper@{\NAT@nmfmt{\NAT@nm}\NAT@date}%
\else
\ifx\NAT@last@nm\NAT@nm\NAT@yrsep
\ifx\NAT@last@yr\NAT@year
\def\NAT@temp{{?}}%
\ifx\NAT@temp\NAT@exlab\PackageWarningNoLine{natbib}%
{Multiple citation on page \thepage: same authors and
year\MessageBreak without distinguishing extra
letter,\MessageBreak appears as question mark}\fi
\NAT@hyper@{\NAT@exlab}%
\else\unskip\NAT@spacechar
\NAT@hyper@{\NAT@date}%
\fi
\else
\@citea\NAT@hyper@{%
\NAT@nmfmt{\NAT@nm}%
\hyper@natlinkbreak{%
\NAT@aysep\NAT@spacechar}{\@citeb\@extra@b@citeb
}%
\NAT@date
}%
\fi
\fi
\or\@citea\NAT@hyper@{\NAT@nmfmt{\NAT@nm}}%
\or\@citea\NAT@hyper@{\NAT@date}%
\or\@citea\NAT@hyper@{\NAT@alias}%
\fi \NAT@def@citea
\else
\ifcase\NAT@ctype
\if\relax\NAT@date\relax
\@citea\NAT@hyper@{\NAT@nmfmt{\NAT@nm}}%
\else
\ifx\NAT@last@nm\NAT@nm\NAT@yrsep
\ifx\NAT@last@yr\NAT@year
\def\NAT@temp{{?}}%
\ifx\NAT@temp\NAT@exlab\PackageWarningNoLine{natbib}%
{Multiple citation on page \thepage: same authors and
year\MessageBreak without distinguishing extra
letter,\MessageBreak appears as question mark}\fi
\NAT@hyper@{\NAT@exlab}%
\else
\unskip\NAT@spacechar
\NAT@hyper@{\NAT@date}%
\fi
\else
\@citea\NAT@hyper@{%
\NAT@nmfmt{\NAT@nm}%
\hyper@natlinkbreak{\NAT@spacechar\NAT@@open\if*#1*\else#1\NAT@spacechar\fi}%
{\@citeb\@extra@b@citeb}%
\NAT@date
}%
\fi
\fi
\or\@citea\NAT@hyper@{\NAT@nmfmt{\NAT@nm}}%
\or\@citea\NAT@hyper@{\NAT@date}%
\or\@citea\NAT@hyper@{\NAT@alias}%
\fi
\if\relax\NAT@date\relax
\NAT@def@citea
\else
\NAT@def@citea@close
\fi
\fi
}}\ifNAT@swa\else\if*#2*\else\NAT@cmt#2\fi
\if\relax\NAT@date\relax\else\NAT@@close\fi\fi}{#1}{#2}}
\makeatother
\begin{filecontents}{\jobname.bib}
@book{aardvark,
author = {Anne Aardvark},
title = {Ardvarking},
year = {2020},
}
@book{zebra,
author = {Zoe Zebra},
title = {Zebraing},
year = {2010},
}
\end{filecontents}
\begin{document}
\citep{zebra,aardvark}
\citep{aardvark,zebra}
\bibliography{\jobname}
\end{document}