【问题标题】:How to replace square brackets with curly brackets using R's regex?如何使用 R 的正则表达式用大括号替换方括号?
【发布时间】:2016-02-10 00:51:54
【问题描述】:

由于 pandoc-citeproc 和 latex 之间的转换,我想替换它

[@Fotheringham1981]

有了这个

\cite{Fotheringham1981} .

下面的可重现示例说明了单独处理每个括号的问题。

x <- c("[@Fotheringham1981]", "df[1,2]")
x1 <- gsub("\\[@", "\\\\cite{", x)
x2 <- gsub("\\]", "\\}", x1)

x2[1] # good
## [1] "\\cite{Fotheringham1981}"

x2[2] # bad
## [1] "df[1,2}"

在 C# 中看到了类似的问题 solved,但没有使用 R 的 perly 正则表达式 - 有什么想法吗?

编辑:

它应该能够处理长文档,例如

old_rmd <- "$p = \alpha e^{\beta d}$ [@Wilson1971] and $p = \alpha d^{\beta}$
[@Fotheringham1981]."
new_rmd1 <- gsub("\\[@([^\\]]*)\\]", "\\\\cite{\\1}", old_rmd, perl = T) 
new_rmd2 <- gsub("\\[@([^]]*)]", "\\\\cite{\\1}", old_rmd) 

new_rmd1
## "$p = \alpha e^{\beta d}$ \\cite{Wilson1971} and $p = \alpha d^{\beta}$\n    \\cite{Fotheringham1981}."

new_rmd2
## [1] "$p = \alpha e^{\beta d}$ \\cite{Wilson1971} and $p = \alpha d^{\beta}$\n\\cite{Fotheringham1981}."

【问题讨论】:

  • 正则表达式可以做相反的事情!

标签: regex r pcre brackets


【解决方案1】:

你需要使用捕获组。

x <- c("[@Fotheringham1981]", "df[1,2]")
gsub("\\[@([^\\]]*)\\]", "\\\\cite{\\1}", x, perl=T)
# [1] "\\cite{Fotheringham1981}" "df[1,2]" 

gsub("\\[@(.*?)\\]", "\\\\cite{\\1}", x)
# [1] "\\cite{Fotheringham1981}" "df[1,2]"

【讨论】:

  • 是的,有些人可能对你的感到困惑。
  • 我只想强调,我们应该只逃避必须逃避的东西。如果有办法避免backslash hell,我们应该这样做。
  • @stribizhev 您的答案更简洁,可以转换我的长 .Rmd 文件 - 您应该得到“正确”的答案 IMO!也感谢您的回复 Av,但它似乎不适用于长文档。
  • @RobinLovelace 你是什么意思?他只是避免逃跑。我不知道他的正则表达式如何在我的失败的字符串上工作。你也可以考虑这个gsub("\\[@([^][]*)]", "\\\\cite{\\1}", x)
  • @RobinLovelace 失败了,你需要添加perl=T
【解决方案2】:

你可以使用

gsub("\\[@([^]]*)]", "\\\\cite{\\1}", x)

IDEONE demo

正则表达式分解:

  • \\[@ - 文字 [@ 符号序列
  • ([^]]*) - 捕获组 1,匹配除 ] 之外的任何符号的 0 次或多次出现(请注意,如果 ] 出现在字符类的开头,则不需要转义)
  • ] - 文字 ] 符号

您不需要将perl=T 与此一起使用,因为字符类中的] 不会被转义。否则,将需要使用该选项。

另外,我相信我们应该只逃避必须逃避的东西。如果有办法避免backslash hell,我们应该这样做。因此,您甚至可以使用

gsub("[[]@([^]]*)]", "\\\\cite{\\1}", x)

这里是another demo

为什么基于 TRE 的正则表达式比 PCRE 更有效:

在 R 2.10.0 及更高版本中,默认的正则表达式引擎是 Ville Laurikari 的 TRE 引擎 [source] 的修改版本。匹配所花费的时间library's author states随着输入文本长度的增加而线性增长,而内存需求几乎是恒定的(几十千字节)。 TRE 也是said 以使用可预测和适度的内存消耗以及所用正则表达式匹配算法长度的二次最坏情况时间。这就是为什么在处理较大的文档时最好依赖 TRE 而不是 PCRE 正则表达式。

【讨论】:

  • 所以你的意思是[[]\\[ 好?
  • :) 不,是一样的。在 POSIX 表达式中,转义在字符类内部是不可能的,但在外部是可能的。我只是展示了一个没有转义的同义表达式。
【解决方案3】:

这匹配[@,然后设置一个捕获组,即(...)内的所有内容,然后.*?匹配最短字符串直到]

gsub("\\[(@.*?)\\]", "\\\\cite{\\1}", x)
## [1] "\\cite{@Fotheringham1981}" "df[1,2]" 

这是正则表达式的铁路图:

\[(@.*?)\]

Debuggex Demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多