如何在R中提取这些多个正则表达式组

时间:2018-08-13 13:12:22

标签: r regex regex-group

我具有以下格式的字符串输入:

my.strings <- c("FACT11", "FACT11:FACT20", "FACT1sometext:FACT20", "FACT1text with spaces:FACT20", "FACT14:FACT20", "FACT1textAnd1312:FACT2etc", "FACT12:FACT22:FACT31")

我想提取所有“ FACT”和FACT之后的第一个数字。因此,此示例的结果将是:

c("FACT1", "FACT1 FACT2", "FACT1 FACT2", "FACT1 FACT2", "FACT1 FACT2", "FACT1 FACT2", "FACT1 FACT2 FACT3")

或者,结果可以是一个列表,其中列表中的每个元素都是一个矢量,其中包含1项至3项。

到目前为止,我得到的是:

gsub("(FACT[1-3]).*?:(FACT[1-3]).*", '\\1 \\2', my.strings)
# [1] "FACT11"       "FACT1 FACT2 " "FACT1 FACT2 " "FACT1 FACT2 " "FACT1 FACT2 " "FACT1 FACT2 "
# [7] "FACT1 FACT2 " "FACT1 FACT2 "

看起来不错,除了第一个元素的“ FACT11”而不是“ FACT1”(删除第二个“ 1”),而my.strings的最后一个元素缺少“ FACT3”。但是将另一组添加到gsub会使整个事情搞砸了。

gsub("(FACT[1-3]).*?:(FACT[1-3]).*?:(FACT[1-3]).*?", '\\1 \\2 \\3', my.strings)
# [1] "FACT11"                       "FACT11:FACT20"                "FACT1sometext:FACT20"        
# [4] "FACT1text with spaces:FACT20" "FACT14:FACT20"                "FACT1textAnd1312:FACT2etc"   
# [7] "FACT12:FACT21"                "FACT1 FACT2 FACT31" 

那我该如何正确提取组?

3 个答案:

答案 0 :(得分:5)

您也可以使用基本R方法:

> m <- regmatches(my.strings, gregexpr("FACT[1-3]", my.strings))
> sapply(m, paste, collapse=" ")
[1] "FACT1"            
[2] "FACT1 FACT2"      
[3] "FACT1 FACT2"      
[4] "FACT1 FACT2"      
[5] "FACT1 FACT2"      
[6] "FACT1 FACT2"      
[7] "FACT1 FACT2 FACT3"

使用FACT[1-3](或FACT[0-9]FACT\\d)模式提取所有匹配项,然后用空格“加入”它们。

答案 1 :(得分:4)

一个选项是从str_extract_all中提取stringr,以提取所有'FACT'子字符串,然后将可以是1到3的一个数字([1-3])提取到list中的vector个。然后,maplist元素和pastevector到单个字符串

library(tidyverse)
str_extract_all(my.strings, "FACT[1-3]") %>%
            map_chr(paste, collapse= ' ')
#[1] "FACT1"             "FACT1 FACT2"       "FACT1 FACT2"      
#[4] "FACT1 FACT2"       "FACT1 FACT2"       "FACT1 FACT2"      
#[7] "FACT1 FACT2 FACT3"

或使用gsub中的base R

gsub("\\s{2,}", " ", trimws(gsub("(FACT[1-3])(*SKIP)(*FAIL)|.",
                       " ", my.strings, perl = TRUE)))
#[1] "FACT1"             "FACT1 FACT2"       "FACT1 FACT2"      
#[4] "FACT1 FACT2"       "FACT1 FACT2"       "FACT1 FACT2"      
#[7] "FACT1 FACT2 FACT3"

答案 2 :(得分:0)

另一个R替代基数:

此解决方案使用FACT以一位数字结尾的事实。

my.strings %>%  
  gsub("(\\d)\\d*", "\\1:", ., perl = TRUE) %>% 
  strsplit(":") %>%
  sapply(function(x) paste(x[grepl("FACT", x)], collapse = " "))

[1] "FACT1"             "FACT1 FACT2"       "FACT1 FACT2"       "FACT1 FACT2"      
[5] "FACT1 FACT2"       "FACT1 FACT2"       "FACT1 FACT2 FACT3"