R中的正则expression式组捕获多个捕获组

在R中,是否有可能从正则expression式匹配中提取组捕获? 据我所知, grepgreplregexprgregexprsubgsub gregexpr返回组捕获。

我需要从编码的string中提取键值对:

 \((.*?) :: (0\.[0-9]+)\) 

我总是可以做多个完全匹配的greps,或者做一些外部的(非R)处理,但是我希望我可以在R内完成所有的工作。是否有一个函数或者一个包提供了这样的function呢?

来自stringr包的str_match()将执行此操作。 它为匹配中的每个组返回一个包含一列的字符matrix(以及整个匹配中的一个):

 > s = c("(sometext :: 0.1231313213)", "(moretext :: 0.111222)") > str_match(s, "\\((.*?) :: (0\\.[0-9]+)\\)") [,1] [,2] [,3] [1,] "(sometext :: 0.1231313213)" "sometext" "0.1231313213" [2,] "(moretext :: 0.111222)" "moretext" "0.111222" 

gsub这样做,从你的例子:

 gsub("\\((.*?) :: (0\\.[0-9]+)\\)","\\1 \\2", "(sometext :: 0.1231313213)") [1] "sometext 0.1231313213" 

你需要在引号中加倍转义,然后他们为正则expression式工作。

希望这可以帮助。

尝试regmatches()regexec()

 regmatches("(sometext :: 0.1231313213)",regexec("\\((.*?) :: (0\\.[0-9]+)\\)","(sometext :: 0.1231313213)")) [[1]] [1] "(sometext :: 0.1231313213)" "sometext" "0.1231313213" 

gsub()可以做到这一点,并只返回捕获组:

但是,为了达到此目的,您必须按照gsub()帮助中所述,明确地select捕获组之外的元素。

(…)未被replace的字符向量“x”的元素将被不变地返回。

所以如果你要select的文本位于某个string的中间,那么在捕获组之前和之后添加。*应该允许你只返回它。

gsub(".*\\((.*?) :: (0\\.[0-9]+)\\).*","\\1 \\2", "(sometext :: 0.1231313213)") [1] "sometext 0.1231313213"

我喜欢Perl兼容的正则expression式。 也许别人也是…

这里是一个perl兼容正则expression式的函数,它和我习惯的其他语言的函数的function相匹配:

 regexpr_perl <- function(expr, str) { match <- regexpr(expr, str, perl=T) matches <- character(0) if (attr(match, 'match.length') >= 0) { capture_start <- attr(match, 'capture.start') capture_length <- attr(match, 'capture.length') total_matches <- 1 + length(capture_start) matches <- character(total_matches) matches[1] <- substr(str, match, match + attr(match, 'match.length') - 1) if (length(capture_start) > 1) { for (i in 1:length(capture_start)) { matches[i + 1] <- substr(str, capture_start[[i]], capture_start[[i]] + capture_length[[i]] - 1) } } } matches } 

这就是我最终解决这个问题的方法。 我使用了两个单独的正则expression式来匹配第一个和第二个捕获组,并运行两个gregexpr调用,然后抽出匹配的子string:

 regex.string <- "(?<=\\().*?(?= :: )" regex.number <- "(?<= :: )\\d\\.\\d+" match.string <- gregexpr(regex.string, str, perl=T)[[1]] match.number <- gregexpr(regex.number, str, perl=T)[[1]] strings <- mapply(function (start, len) substr(str, start, start+len-1), match.string, attr(match.string, "match.length")) numbers <- mapply(function (start, len) as.numeric(substr(str, start, start+len-1)), match.number, attr(match.number, "match.length")) 

正如stringr包中所build议的,这可以使用str_match()str_extract()来实现。

从手册改编:

 library(stringr) strings <- c(" 219 733 8965", "329-293-8753 ", "banana", "239 923 8115 and 842 566 4692", "Work: 579-499-7527", "$1000", "Home: 543.355.3679") phone <- "([2-9][0-9]{2})[- .]([0-9]{3})[- .]([0-9]{4})" 

提取和组合我们的小组:

 str_extract(strings, phone) # [1] "219 733 8965" "329-293-8753" NA "239 923 8115" "579-499-7527" NA # [7] "543.355.3679" 

用输出matrix表示组(我们对2+列感兴趣):

 str_match(strings, phone) # [,1] [,2] [,3] [,4] # [1,] "219 733 8965" "219" "733" "8965" # [2,] "329-293-8753" "329" "293" "8753" # [3,] NA NA NA NA # [4,] "239 923 8115" "239" "923" "8115" # [5,] "579-499-7527" "579" "499" "7527" # [6,] NA NA NA NA # [7,] "543.355.3679" "543" "355" "3679" 

utils strcapture解决scheme:

 x <- c("key1 :: 0.01", "key2 :: 0.02") strcapture(pattern = "(.*) :: (0\\.[0-9]+)", x = x, proto = list(key = character(), value = double())) #> key value #> 1 key1 0.01 #> 2 key2 0.02