使用 natbib 对多个引文进行排序

使用 natbib 对多个引文进行排序

我在报告文档类中使用 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}

[土豚,2020,斑马,2010]//[土豚,2020,斑马,2010]


如果你想以不同于参考书目的方式对引文进行排序,则需要做一些额外的工作。我已经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}

(斑马,2010 年;土豚,2020 年)//(斑马,2010 年;土豚,2020 年)

相关内容