正则表达式与 stringr:: 如何找到模式的第一个实例
Regex with stringr:: how to find first instance of pattern
这个问题的背后是提取由 knitr
和 latex
创建的所有引用的努力。没有找到另一种方法,我的想法是读入 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 来匹配 (\r
或 r
+ "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"
这个问题的背后是提取由 knitr
和 latex
创建的所有引用的努力。没有找到另一种方法,我的想法是读入 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 来匹配 (\r
或 r
+ "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"