首页 > 解决方案 > 使用从 LaTeX 文档中提取引用的脚本

问题描述

我试图从 LaTeX 文件中提取所有引用,也就是说,能够提取 \cite 之后的两个花括号之间的所有内容(即,\cite{bla,blo}会给我blablo)。有一些极端情况:\cite{}可能包含一个或多个用逗号分隔的引用(如果只有一个引用,则没有逗号)并且\cite{}命令可能跨越多行。

到目前为止,我想出了以下一种效果很好的班轮:

<file.tex grep -oPz "(?s)(?<=\\\\cite{).[^}]*?(?=})" | tr '\n\0,' ' \n\n' | tr -d '[:blank:]' | sort | uniq

但是,我想知道是否可以只使用一种工具来完成,无论是 sed、grep 还是 awk。我认为在 awk 中这样做会更容易(因为 sort | uniq 部分可以在 awk 中轻松完成,但我被困在提取部分)。

欢迎任何建议。

这是一个测试用例:

Aenean consequat \cite{acitation} auctor varius. Pellentesque varius,
 sapien quis faucibus rhoncus, nunc nisl sagittis erat, ac varius magna
 quam eu est. Pellentesque \cite{a citation with spaces is considered
 valid yes but does not produce the correct output but it is not a problem
 because those are not valid in LaTeX} congue maximus efficitur. Quisque
 ac aliquam nisi. Nullam sit
 amet auctor metus, nec varius ipsum. Proin vel lacus sed nisl auctor
 porttitor. Sed id turpis pretium, rhoncus nisi eu, dictum ipsum. Nulla
 facilisi. Vestibulum sed congue \cite{some.citation.here, anotherone} 
metus, vitae \cite{onecitation,
thenexthere} scelerisque sem.Vestibulum eget gravida ante. Suspendisse 
consequat libero eget mauris cursus, sed blandit est euismod. Pellentesque
 porta vitae dolor blandit lacinia. Nulla sit amet rutrum velit, in mollis
 sem. Nunc gravida consectetur \cite{acitation} feugiat.

和输出

acitation
acitationwithspacesisconsideredvalidyesbutdoesnotproducethecorrectoutputbutitisnotaproblembecausethosearenotvalidinLaTeX
anotherone
onecitation
some.citation.here
thenexthere

只要每个引文只列出一次,输出的顺序就无关紧要。结果为

\cite{a citation with spaces is considered
 valid yes but does not produce the correct output but it is not a problem
 because those are not valid in LaTeX}

是未定义的行为,因为它不应出现在有效的 LaTeX 文档中。

标签: bashawksedgrep

解决方案


您能否尝试以下操作(因为我在移动设备上无法测试它,应该可以但是)。

awk -v RS="" '{while(match($0,/\\cite{[^}]*/)){val=substr($0,RSTART+6,RLENGTH-6);array[val]++;$0=substr($0,RSTART+RLENGTH)}} END{for(i in array){if(array[i]==1){gsub(/,/,ORS,i);print i}}}' Input_File

编辑:

BEGIN {
  RS=""
}

{
  gsub(/ *, */, ",", $0);
  gsub(/ |\n/, "", $0);
  while (match($0,/\\cite{[^}]*/)) {
    val = substr($0, RSTART+6, RLENGTH-6);
    split(val, array, ",");
    for (x in array)
      citations[array[x]]++
    $0 = substr($0, RSTART + RLENGTH)
  }
}

END {
  for(i in citations)
      print i
}

推荐阅读