我有一个字符串以及在多个括号内提取信息的内容.目前,我可以使用下面的代码从最后一个括号中提取信息.我该怎么做才能提取多个括号并作为向量返回?
j <- "What kind of cheese isn't your cheese? (wonder) Nacho cheese! (groan) (Laugh)"
sub("\\).*", "", sub(".*\\(", "", j))
Run Code Online (Sandbox Code Playgroud)
目前的输出是:
[1] "Laugh"
Run Code Online (Sandbox Code Playgroud)
期望的输出是:
[1] "wonder" "groan" "Laugh"
Run Code Online (Sandbox Code Playgroud)
koh*_*ske 53
这是一个例子:
> gsub("[\\(\\)]", "", regmatches(j, gregexpr("\\(.*?\\)", j))[[1]])
[1] "wonder" "groan" "Laugh"
Run Code Online (Sandbox Code Playgroud)
我认为这应该运作良好:
> regmatches(j, gregexpr("(?=\\().*?(?<=\\))", j, perl=T))[[1]]
[1] "(wonder)" "(groan)" "(Laugh)"
Run Code Online (Sandbox Code Playgroud)
但结果包括括号......为什么?
这有效:
regmatches(j, gregexpr("(?<=\\().*?(?=\\))", j, perl=T))[[1]]
Run Code Online (Sandbox Code Playgroud)
感谢@MartinMorgan的评论.
Das*_*son 21
使用stringr包我们可以减少一点.
library(stringr)
# Get the parenthesis and what is inside
k <- str_extract_all(j, "\\([^()]+\\)")[[1]]
# Remove parenthesis
k <- substring(k, 2, nchar(k)-1)
Run Code Online (Sandbox Code Playgroud)
@kohske使用regmatches,但我目前正在使用2.13,因此目前无法访问该功能.这增加了对stringr的依赖,但我认为它更容易使用,代码更清晰一些(好吧......就像使用正则表达式一样明确......)
编辑:我们也可以尝试这样的事情 -
re <- "\\(([^()]+)\\)"
gsub(re, "\\1", str_extract_all(j, re)[[1]])
Run Code Online (Sandbox Code Playgroud)
这个通过在正则表达式中定义标记的子表达式来工作.它提取与正则表达式匹配的所有内容,然后gsub仅提取子表达式内的部分.
我认为基本上有3种简单的方法可以提取R中的多个捕获组(不使用替换)。str_match_all,str_extract_all和regmatches/gregexpr组合。
我喜欢@kohske的正则表达式,它的后面是一个开放的括号?<=\\(,后面是一个封闭的括号?=\\),并且在中间(懒惰地)抓取了所有内容,.+?换句话说(?<=\\().+?(?=\\))
使用相同的正则表达式:
str_match_all返回答案作为矩阵。
str_match_all(j, "(?<=\\().+?(?=\\))")
[,1]
[1,] "wonder"
[2,] "groan"
[3,] "Laugh"
# Subset the matrix like this....
str_match_all(j, "(?<=\\().+?(?=\\))")[[1]][,1]
[1] "wonder" "groan" "Laugh"
Run Code Online (Sandbox Code Playgroud)
str_extract_all以列表形式返回答案。
str_extract_all(j, "(?<=\\().+?(?=\\))")
[[1]]
[1] "wonder" "groan" "Laugh"
#Subset the list...
str_extract_all(j, "(?<=\\().+?(?=\\))")[[1]]
[1] "wonder" "groan" "Laugh"
Run Code Online (Sandbox Code Playgroud)
regmatches/gregexpr还返回答案作为列表。由于这是基本的R选项,因此有些人喜欢它。注意建议perl = TRUE。
regmatches(j, gregexpr( "(?<=\\().+?(?=\\))", j, perl = T))
[[1]]
[1] "wonder" "groan" "Laugh"
#Subset the list...
regmatches(j, gregexpr( "(?<=\\().+?(?=\\))", j, perl = T))[[1]]
[1] "wonder" "groan" "Laugh"
Run Code Online (Sandbox Code Playgroud)
如果我误解了最流行的选项,希望SO社区可以更正/编辑此答案。
使用rex可以使这种类型的任务更简单一些.
matches <- re_matches(j,
rex(
"(",
capture(name = "text", except_any_of(")")),
")"),
global = TRUE)
matches[[1]]$text
#>[1] "wonder" "groan" "Laugh"
Run Code Online (Sandbox Code Playgroud)