Latex系列之——在参考文献列表中从第3位作者处截断,并将后续作者变成 et. al(通过修改bst文件实现)

问题描述

在用latex对文章排版时,发现在参考文献列表中,有的文章作者人数很多,一篇文章的作者就能占好几页,所以必须要做到从某一作者处截断作者列表,让后续作者都变成et. al。

但是往上的相关资源却是很少,通常是有2种方法,一种是用makebst,一种是自己手动修改bst文件。这里用的是第二种,bst文件中涉及作者列表的函数如下:

FUNCTION {format.names}
{ 'bibinfo :=
  duplicate$ empty$ 'skip$ {
  's :=
  "" 't := 
  #1 'nameptr :=
  s num.names$ 'numnames :=
  numnames 'namesleft :=
    { namesleft #0 > }
    { s nameptr
      "{vv~}{ll}{ f{~}}{ jj}"
      format.name$
      remove.dots
      bibinfo bibinfo.check
      't :=
      nameptr #1 >
        {
          namesleft #1 >
            { ", " * t * }
            {
              s nameptr "{ll}" format.name$ duplicate$ "others" =
                { 't := }
                { pop$ }
              if$
              "," *
              t "others" =
                {
                  " " * bbl.etal *
                }
                { " " * t * }
              if$
            }
          if$
        }
        't
      if$
      nameptr #1 + 'nameptr :=
      namesleft #1 - 'namesleft :=
    }
  while$
  } if$
}

不熟悉Bibtex语法的可能很容易被各种教程搞得云里雾里,但经过研究,这段代码的意思是这样(看%后面的注释):

FUNCTION {format.names}
{ 'bibinfo :=
  duplicate$ empty$ 'skip$ {
  's :=
  "" 't := 
  #1 'nameptr :=
  s num.names$ 'numnames :=
  numnames 'namesleft :=
    { namesleft #0 > } %combine with "while"
    { s nameptr
      "{vv~}{ll}{ f{~}}{ jj}"
      format.name$
      remove.dots
      bibinfo bibinfo.check
      't := %let t = s[nameptr] in that be formated, and modify t below
      nameptr #1 >
        {
          namesleft #1 >
            { ", " * t * }
            { % If final author's name is 'others', let 'others' change to 'bbl.etal
              s nameptr "{ll}" format.name$ duplicate$ "others" =
                { 't := }%if true, let t = others
                { pop$ }%if not
              if$
              "," * %like ", " in { ", " * t * }. between final author's name and et.al
              t "others" =
                {
                  " " * bbl.etal *
                }
                { " " * t * }
              if$
            }
          if$
        }
        't
      if$
      nameptr #1 + 'nameptr :=
      namesleft #1 - 'namesleft :=
    }
  while$
  } if$
}

看懂这段代码这里需要对BibTex的一些基本语法有所了解:
1.在BibTex中,赋值是通过:=实现,而不是=实现,如相将变量A赋值给变量B,应该用如下语句:
A ‘B :=
2.在BibTex中,if-else,或者其它判断语句的嵌套结构是:

条件语句(如a #1 >)
{}如果条件语句为真执行的
{}如果条件语句为假执行的
if¥
有2个“{}”
3.了解一些内置的函数如skip 、 p o p 、pop pop


解决方案:

FUNCTION {format.names}
{ 'bibinfo :=
  duplicate$ empty$ 'skip$ {
  's :=
  "" 't := 
  #1 'nameptr :=
  #0 'num_already_define_by_jlzeng :=
  s num.names$ 'numnames :=
  numnames 'namesleft :=
    { namesleft #0 > } %combine with "while"
    { s nameptr
      "{vv~}{ll}{ f{~}}{ jj}"
      format.name$
      remove.dots
      bibinfo bibinfo.check
      't := %let t = s[nameptr] in that be formated, and modify t below
      nameptr #1 >
        {
          %--------------------自己写的部分--------------------
          nameptr 'num_already_define_by_jlzeng :=
          num_already_define_by_jlzeng #4 <
            { ", " * t * }
            { 
              namesleft #1 >
                {skip$}
                {
                  "." * bbl.etal * 
                }
              if$
            }
          if$
          %--------------------自己写的部分--------------------
          
        }
        't
      if$
      nameptr #1 + 'nameptr :=
      namesleft #1 - 'namesleft :=
    }
    while$
  } if$
}

新定义一个变量num_already_define_by_jlzeng,储存已经处理的作者个数,如果这个数量小于4,则通过
{ ", " * t * }
继续添加作者,如果这个数量大于4,并且剩余作者数量满足
namesleft #1 >

{skip$}
,不处理这些作者,如果已经处理到最后一个作者,就通过
{
“.” * bbl.etal *
}
加上et.al。

有问题的话欢迎留言,看到会第一时间解答,转载请注明出处。
码字不易,如果感觉有帮助的话点个赞吧~

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值