![自动解析 .bib 数据库中的重复引用键](https://linux22.com/image/354336/%E8%87%AA%E5%8A%A8%E8%A7%A3%E6%9E%90%20.bib%20%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%E7%9A%84%E9%87%8D%E5%A4%8D%E5%BC%95%E7%94%A8%E9%94%AE.png)
我目前的工作流程是
- 编辑引用数据库在线
wget http://www.citeulike.org/bibtex/user/MYUSER/tag/MYTAG?key_type=4
biber biblio
pdflatex biblio
其中biblio.tex
是使用 生成的参考书目/参考文献列表文件\nocite{*}
。
问题在于,生成 AuthorYearTitle 键(key_type=4
在wget
上面的 URL 中)的 CiteULike 算法可能会产生冲突,即两个具有相同键的不同条目。
虽然这肯定是 CiteULike 的错误,但我想通过在和之间插入另一个步骤来修补此问题,wget
该biber
步骤重写.bib
数据库以解析重复的键,在重复的 AuthorYearTitle 键后插入尾随的“a”、“b”...字母。(编辑:我想保留一个 AuthorYearTitle 键,以防参考书目需要进一步编辑。)
我想要一个不需要用户干预的解决方案,以便步骤 2.、3.、4.... 可以在脚本中运行。
我无法找到这个(简单?)问题的现有解决方案,在重新发明轮子之前,我想在这个论坛上寻求建议。
笔记
通过省略参数key_type=4
,可以得到唯一的数字键(citeulike:123456
),因此一个可能的策略是使用更强大的密钥生成器并忘记由 CiteULike 生成的密钥。
答案1
由于您使用的是\nocite{*}
,因此您不需要 bib 标签来表示任何有意义的内容。因此,一个简单的解决方案就是.bib
用一些随机字符序列替换文件中的所有标签(或附加一个,见下文)。对我来说,这有效:
sed -i -e 's~^@\(.\+\){.\+,$~(echo @\1{; cat /dev/urandom | tr -dc "a-zA-Z0-9" | fold -w 8 | head -1; echo ,) | paste -sd ""~e' biblio.bib
这是起什么作用的?
sed
好吧,打电话sed
-i
进行内联替换
-e
使用扩展正则表达式(用于捕获组和替换)
'
开始sed
命令
s
代替
~
替换起始分隔符
^@\(.\+\){.\+,$
搜索行首,,@
一组非空白,后跟{
,另一组非空白,,,
行尾;例如,@article{AuthorYear,
~
替换中间分隔符
(echo @\1{; cat /dev/urandom | tr -dc "a-zA-Z0-9" | fold -w 8 | head -1; echo ,) | paste -sd ""
替换为
- echo
@
,先前捕获的第一个非空白组,{
- 回显一个随机标签(
cat
通过head
) - 回声
,
(删除中间的换行符后paste
)
~
替代结束定界符
e
将替换作为 shell 命令调用,并使用输出作为替换文本
'
结束sed
命令
biblio.bib
文件名
更新 1如果您想保留原始标签,只需捕获它们并附加随机标签:
sed -i -e 's~^@\(.\+\){\(.\+\),$~(echo @\1{\2_; cat /dev/urandom | tr -dc "a-zA-Z0-9" | fold -w 8 | head -1; echo ,) | paste -sd ""~e' biblio.bib
更新 2这不是用随机标签替换,而是将a
、b
、 ... 添加到标签中之前曾被见过;因此第一次出现的“AuthorYear”保持不变,第二次出现的变为“AuthorYeara”,依此类推。
echo > cache
sed -i -e 's~^@\(.\+\){\(.\+\),$~(echo @\1{\2; awk "BEGIN{printf \\\"%c\\\", 96+`grep \2 cache | wc -l`}" | sed "s/\\\`//"; echo \2 >> cache; echo ,) | paste -sd ""~e' biblio.bib
当然可以改为第二个“b”:
echo > cache
sed -i -e 's~^@\(.\+\){\(.\+\),$~(echo @\1{\2; awk "BEGIN{printf \\\"%c\\\", 97+`grep \2 cache | wc -l`}" | sed "s/a//"; echo \2 >> cache; echo ,) | paste -sd ""~e' biblio.bib