当出现次数未知时,如何用反向引用进行替换?
How to do a replace with backreferences, when the number of occurences is unknown?
为了对 Bookdown 生成的 .tex 文件进行一些更正,我需要在引用中使用 ,
替换出现的 }{
,即
s <- "Text.\autocites{REF1}{REF2}{REF3}. More text \autocites{REF4}{REF5} and \begin{tabular}{ll}"
应该变成
"Text.\autocites{REF1,REF2,REF3}. More text \autocites{REF4,REF5} and \begin{tabular}{ll}
因为我需要保留引用,所以我尝试查看反向引用,但我似乎做错了,因为事先不知道要匹配的组数。另外,我不能做 stringr::str_replace_all(s, "\}\{", ",")
,因为 }{
也出现在文档的其他地方。
到目前为止,我最好的方法是使用回溯仅在 \autocites
之后发生时才进行替换,但是我无法获得正确的反向引用和分组:
stringr::str_replace_all(s, "(?<=\\autocites\{)([:alnum:]+)(\}\{)", "\1,")
[1] "Text.\autocites{REF1,REF2}{REF3}. More text \autocites{REF4,REF5} and \begin{tabular}{ll}"
stringr::str_replace_all(s, "(?<=\\autocites\{)([:alnum:]+)((\}\{)([:alnum:]+))*", "\1,\4")
[1] "Text.\autocites{REF1,REF3}. More text \autocites{REF4,REF5} and \begin{tabular}{ll}"
我可能遗漏了一些非常明显的方法,所以我希望有人能提供帮助。
很酷的问题 - 我学会了 str_replace
的新技巧。您可以使 return 值成为一个函数,并将该函数应用于您选择的字符串。
replace_brakets <- function(str) {
str_replace_all(str, "\}\{", ",")
}
s %>% str_replace_all("(?<=\\autocites\{)([:alnum:]+\}\{)+", replace_brakets)
# [1] "Text.\autocites{REF1,REF2,REF3}. More text \autocites{REF4,REF5} and \begin{tabular}{ll}"
pat
匹配
autocites
后跟
- 以
}
结尾的最短字符串是
- 后跟字符串结尾或非
{
然后使用 gsubfn
将其中出现的每个 }{
替换为逗号。它使用公式表示法来表示替换函数——函数体在 ~
的 RHS 上,因为函数体包含 ..1
参数被认为是 ...
。它不使用零宽度先行或后行。
library(gsubfn)
pat <- "(autocites.*?\}($|[^{]))"
gsubfn(pat, ~ gsub("}{", ",", ..1, fixed = TRUE), s)
给予:
[1] "Text.\autocites{REF1,REF2,REF3}. More text \autocites{REF4,REF5} and \begin{tabular}{ll}"
变化
上面显示的正则表达式的一个小的简化是从 pat
中删除外括号,而是在 gsubfn
中指定 backref = 0
。这告诉它将整个匹配传递给函数。我们可以像上面那样使用 ..1
来指定参数,但是因为我们知道必须只传递一个参数,所以我们可以在函数体中将它指定为 x
。任何变量名都会像它假定任何自由变量是一个参数那样做。输出与上面相同。
pat2 <- "autocites.*?\}($|[^{])"
gsubfn(pat2, ~ gsub("}{", ",", x, fixed = TRUE), s, backref = 0)
为了对 Bookdown 生成的 .tex 文件进行一些更正,我需要在引用中使用 ,
替换出现的 }{
,即
s <- "Text.\autocites{REF1}{REF2}{REF3}. More text \autocites{REF4}{REF5} and \begin{tabular}{ll}"
应该变成
"Text.\autocites{REF1,REF2,REF3}. More text \autocites{REF4,REF5} and \begin{tabular}{ll}
因为我需要保留引用,所以我尝试查看反向引用,但我似乎做错了,因为事先不知道要匹配的组数。另外,我不能做 stringr::str_replace_all(s, "\}\{", ",")
,因为 }{
也出现在文档的其他地方。
到目前为止,我最好的方法是使用回溯仅在 \autocites
之后发生时才进行替换,但是我无法获得正确的反向引用和分组:
stringr::str_replace_all(s, "(?<=\\autocites\{)([:alnum:]+)(\}\{)", "\1,")
[1] "Text.\autocites{REF1,REF2}{REF3}. More text \autocites{REF4,REF5} and \begin{tabular}{ll}"
stringr::str_replace_all(s, "(?<=\\autocites\{)([:alnum:]+)((\}\{)([:alnum:]+))*", "\1,\4")
[1] "Text.\autocites{REF1,REF3}. More text \autocites{REF4,REF5} and \begin{tabular}{ll}"
我可能遗漏了一些非常明显的方法,所以我希望有人能提供帮助。
很酷的问题 - 我学会了 str_replace
的新技巧。您可以使 return 值成为一个函数,并将该函数应用于您选择的字符串。
replace_brakets <- function(str) {
str_replace_all(str, "\}\{", ",")
}
s %>% str_replace_all("(?<=\\autocites\{)([:alnum:]+\}\{)+", replace_brakets)
# [1] "Text.\autocites{REF1,REF2,REF3}. More text \autocites{REF4,REF5} and \begin{tabular}{ll}"
pat
匹配
autocites
后跟- 以
}
结尾的最短字符串是 - 后跟字符串结尾或非
{
然后使用 gsubfn
将其中出现的每个 }{
替换为逗号。它使用公式表示法来表示替换函数——函数体在 ~
的 RHS 上,因为函数体包含 ..1
参数被认为是 ...
。它不使用零宽度先行或后行。
library(gsubfn)
pat <- "(autocites.*?\}($|[^{]))"
gsubfn(pat, ~ gsub("}{", ",", ..1, fixed = TRUE), s)
给予:
[1] "Text.\autocites{REF1,REF2,REF3}. More text \autocites{REF4,REF5} and \begin{tabular}{ll}"
变化
上面显示的正则表达式的一个小的简化是从 pat
中删除外括号,而是在 gsubfn
中指定 backref = 0
。这告诉它将整个匹配传递给函数。我们可以像上面那样使用 ..1
来指定参数,但是因为我们知道必须只传递一个参数,所以我们可以在函数体中将它指定为 x
。任何变量名都会像它假定任何自由变量是一个参数那样做。输出与上面相同。
pat2 <- "autocites.*?\}($|[^{])"
gsubfn(pat2, ~ gsub("}{", ",", x, fixed = TRUE), s, backref = 0)