尝试对 bookdown 文档的 LaTeX(pdf_book
输出)进行后处理以折叠 biblatex 引用,以便能够使用 \usepackage[sortcites]{biblatex}
按时间顺序对它们进行排序稍后的。因此,我需要在 \\autocites
之后找到 }{
并将其替换为 ,
。我正在试验 gsub()
但找不到正确的咒语。
# example input
testcase <- "text \\autocites[cf.~][]{foxMapping2000}{wattPattern1947}{runkleGap1990} text {keep}{separate}"
# desired output
"text \\autocites[cf.~][]{foxMapping2000,wattPattern1947,runkleGap1990} text {keep}{separate}"
一个简单的方法是替换所有 }{
> gsub('\\}\\{', ',', testcase, perl=TRUE)
[1] "text \\autocites[cf.~][]{foxMapping2000,wattPattern1947,runkleGap1990} text {keep,separate}"
但这也会折叠 {keep}{separate}
。
然后我试图通过使用不同的组来替换以 \\autocites
开头的“单词”(没有空格的字符串)中的 }{
并且失败了:
> gsub('(\\\\autocites)([^ \f\n\r\t\v}{}]+)((\\}\\{})+)', '\\1\\2\\3', testcase, perl=TRUE)
[1] "text \\autocites[cf.~][]{foxMapping2000}{wattPattern1947}{runkleGap1990} some text {keep}{separate}"
附录:
实际文档包含比上面的测试用例更多的行/元素。并非所有元素都包含 \\autocites
,在极少数情况下,一个元素包含多个 \\autocites
。我最初并不认为这是相关的。一个更真实的测试用例:
testcase2 <- c("some text",
"text \\autocites[cf.~][]{foxMapping2000}{wattPattern1947}{runkleGap1990} text {keep}{separate}",
"text \\autocites[cf.~][]{foxMapping2000}{wattPattern1947}{runkleGap1990} text {keep}{separate} \\autocites[cf.~][]{foxMapping2000}{wattPattern1947}")
最佳答案
单个 gsub
调用就足够了:
gsub("(?:\\G(?!^)|\\\\autocites)\\S*?\\K}{", ",", testcase, perl=TRUE)
## => [1] "text \\autocites[cf.~][]{foxMapping2000,wattPattern1947,runkleGap1990} text {keep}{separate}"
参见 regex demo .这里,(?:\G(?!^)|\\autocites)
匹配上一个匹配的末尾或 \autocites
字符串,然后它匹配任意 0 个或多个非空白字符,但尽可能少,然后 \K
丢弃当前匹配缓冲区中的文本并使用最终被逗号替换的 }{
子字符串。
还有一个非常可读的解决方案,其中包含一个正则表达式和一个使用 stringr::str_replace_all
的固定文本替换:
library(stringr)
str_replace_all(testcase, "\\\\autocites\\S+", function(x) gsub("}{", ",", x, fixed=TRUE))
# => [1] "text \\autocites[cf.~][]{foxMapping2000,wattPattern1947,runkleGap1990} text {keep}{separate}"
这里,\\autocites\S+
匹配 \autocites
然后是 1+ 个非空白字符,并且 gsub("}{", ",", x, fixed=TRUE)
将匹配文本中的每个 }{
替换(非常快)为 ,
。
关于正则表达式替换 R 中字符串的部分/组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58543179/