正则表达式与 stringr:: 如何找到模式的第一个实例

Regex with stringr:: how to find first instance of pattern

这个问题的背后是提取由 knitrlatex 创建的所有引用的努力。没有找到另一种方法,我的想法是读入 R .Rnw 脚本并使用正则表达式查找引用——其中乳胶语法为 \ref{caption referenced to}。我的脚本有 250 多个引用,有些彼此非常接近。

下面的 text.1 示例有效,但文本示例无效。我认为这与 R 嘎嘎作响到最后的右括号有关。如何在第一个右大括号处停止并将其之前的内容提取到左大括号?

library(stringr)
text.1 <- c(" \ref{test}", "abc", "\ref{test2}", " \section{test3}", "{test3")
# In the regular expression below, look back and if find "ref{", grab everything until look behind for } at end
# braces are special characters and require escaping with double backslacs for R to recognize them as braces
# unlist converts the list returned by str_extract to a vector

unlist(str_extract_all(string = text.1, pattern = "(?<=ref\{).*(?=\}$)"))
[1] "test"  "test2"

# a more complicated string, with more than one set of braces in an element
text <- c("text \ref{?bar labels precision} and more text  \ref{?table column alignment}", "text \ref{?table space} }")

unlist(str_extract_all(string = text, pattern = "(?<=ref\{).*(?=\}$)"))
character(0)

已编辑

它没有捕获右大括号 } 之前的内容的原因是因为您添加了行尾锚点 $。删除 $ 即可。

因此,你的新代码应该是这样的

 unlist(str_extract_all(string = text, pattern = "(?<=ref\{)[^}]*(?=\})"))

DEMO

text 的问题是 "ref" 前面的反斜杠被引擎和 R 的解析器解释为回车符 return \r;所以你试图匹配 "ref" 但实际上是 (CR + "ef") ...

另外,* 默认是 greedy,这意味着它将尽可能多地匹配,并且仍然允许正则表达式的其余部分匹配。使用 *? 或否定字符 class 来防止贪婪。

unlist(str_extract_all(text, '(?<=\ref\{)[^}]*'))
# [1] "?bar labels precision"   "?table column alignment" "?table space"

如您所见,您可以使用字符 class 来匹配 (\rr + "ef") ...

x <- c(' \ref{test}', 'abc', '\ref{test2}', ' \section{test3}', '{test3',
       'text \ref{?bar labels precision} and more text  \ref{?table column alignment}', 
       'text \ref{?table space} }')

unlist(str_extract_all(x, '(?<=[\rr]ef\{)[^}]*'))

# [1] "test"                    "test2"                   "?bar labels precision"  
# [4] "?table column alignment" "?table space"