我试图从 LaTeX 文件中提取所有引文,也就是说,能够提取 \cite 后面两个大括号之间的所有内容(即,cite{bla,blo}
会给我bla
和blo
(。有几种极端情况:cite{}
可能包含一个或多个以逗号分隔的引文(如果只有一个引文,则没有逗号(,并且cite{}
命令可能跨越多行。
到目前为止,我想出了以下一个运行良好的衬里:
<file.tex grep -oPz "(?s)(?<=\\cite{).[^}]*?(?=})" | tr 'n ,' ' nn' | 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 文档中。
您能否尝试以下操作(因为我在移动设备上无法测试它,应该可以,但是(。
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
}
这可能对你有用(GNU sed(:
sed -n '/n/bb;/\cite{/!b;s//n/;s/.*n/n/;:a;/}/!{N;s/n//2;ba};s//n/;D;:b;s/^([^n]*),s*/1n/;P;D' file
此 sed 脚本使用D
命令删除并包括模式空间中的第一个n
(如果有(的事实,然后将模式空间的剩余部分呈现给 sed 循环。如果模式空间为空,它的行为方式与d
命令相同,并将下一行(减去其换行符(提取到模式空间中,并像往常一样启动 sed 循环。
该脚本分为两部分:如果模式空间包含换行符(仅当它已被处理并引入了换行符时才可能(,则将其传递给:b
goto 标记,否则按以下方式处理模式空间。
如果模式空间不包含\cite{
则将其删除并重复 sed 循环。否则,模式空间将缩短到引文的开头并插入换行符。由结束}
标记的引文的结尾也替换为换行符(在引文流过一行或多行的情况下使用循环(,然后使用D
命令调度 sed 再次运行。
在返回时,删除了第一个引入的换行符后,引文现在位于模式空间的开头。通过将第二个引入的换行符替换,
的换行符来打印单独的引文,并且重复 sed 循环,直到到达引文的结束。然后重复处理模式的其余部分,直到它为空或不包含任何进一步的引用。