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

How can I extract these multiple regex groups in R

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

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 个项目。

到目前为止我得到的是:

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”),并且缺少最后一个元素的 "FACT3" my.strings 个。但是将另一个组添加到 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" 

那么如何正确提取组?

一个选项是 str_extract_allstringr 提取所有 'FACT' 子字符串,后跟一个可以是 1 到 3 ([1-3]) 的数字到 listvector 秒。然后,map 通过 list 元素和 paste vector 到单个字符串

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"

或使用 base R

中的 gsub
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"

您也可以使用基础 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)模式的匹配项,然后 "join" 使用 space。

另一种基础 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"