我有一个字符串以及在多个括号内提取信息的内容。目前,我可以使用下面的代码从最后一个括号中提取信息。我该怎么做才能提取多个括号并作为向量返回?
j <- "What kind of cheese isn't your cheese? (wonder) Nacho cheese! (groan) (Laugh)"
sub("\\).*", "", sub(".*\\(", "", j))
当前输出为:
[1] "Laugh"
所需的输出是:
[1] "wonder" "groan" "Laugh"
答案 0 :(得分:49)
以下是一个例子:
> gsub("[\\(\\)]", "", regmatches(j, gregexpr("\\(.*?\\)", j))[[1]])
[1] "wonder" "groan" "Laugh"
我认为这应该运作良好:
> regmatches(j, gregexpr("(?=\\().*?(?<=\\))", j, perl=T))[[1]]
[1] "(wonder)" "(groan)" "(Laugh)"
但结果包括括号......为什么?
这有效:
regmatches(j, gregexpr("(?<=\\().*?(?=\\))", j, perl=T))[[1]]
感谢@MartinMorgan的评论。
答案 1 :(得分:18)
使用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)
@kohske使用regmatches但我目前正在使用2.13,所以目前无法访问该功能。这增加了对stringr的依赖,但我觉得它更容易使用,代码更清晰一点(好吧......就像使用正则表达式一样明确......)
编辑:我们也可以尝试这样的事情 -
re <- "\\(([^()]+)\\)"
gsub(re, "\\1", str_extract_all(j, re)[[1]])
这个通过在正则表达式中定义标记的子表达式来工作。它提取与正则表达式匹配的所有内容,然后gsub仅提取子表达式中的部分。
答案 2 :(得分:5)
使用rex可能会使这类任务变得更简单。
matches <- re_matches(j,
rex(
"(",
capture(name = "text", except_any_of(")")),
")"),
global = TRUE)
matches[[1]]$text
#>[1] "wonder" "groan" "Laugh"
答案 3 :(得分:4)
我认为基本上有三种简单的方法可以提取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"
str_extract_all
将答案作为列表返回。
str_extract_all(j, "(?<=\\().+?(?=\\))")
[[1]]
[1] "wonder" "groan" "Laugh"
#Subset the list...
str_extract_all(j, "(?<=\\().+?(?=\\))")[[1]]
[1] "wonder" "groan" "Laugh"
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"
希望,如果我误解了最受欢迎的选项,那么SO社区将纠正/编辑此答案。