我想以任何顺序提取猫和狗
string1 <- "aasdfadsf cat asdfadsf dog"
string2 <- "asfdadsfads dog asdfasdfadsf cat"
我现在提取的是猫和狗,还有中间的文本
stringr::str_extract(string1, "cat.*dog|dog.*cat"
我希望输出是
cat dog
和
dog cat
分别用于string1和string2
最佳答案
您可以将sub
与以下PCRE正则表达式一起使用:
.*(?|(dog).*(cat)|(cat).*(dog)).*
请参见regex demo。
细节
.*
-除换行符之外的任何0+字符(要匹配所有字符,请在模式开头添加(?s)
)(?|(dog).*(cat)|(cat).*(dog))
-与两个备选方案之一匹配的分支重置组(?|...|...)
:(dog).*(cat)
-组1捕获dog
,然后尽可能多的0个字符,组2捕获cat
|
-或(cat).*(dog)
-组1捕获cat
,然后尽可能多的0+个字符,组2捕获dog
(在分支重置组中,组ID重置为组+ 1之前的值).*
-除换行符以外的任何0+个字符\1 \2
替换模式将Group 1和Group 2的值插入到结果字符串中(这样,结果只是dog
或cat
,一个空格和一个cat
或dog
)。也请参见an R demo online:
x <- c("aasdfadsf cat asdfadsf dog", "asfdadsfads dog asdfasdfadsf cat")
sub(".*(?|(dog).*(cat)|(cat).*(dog)).*", "\\1 \\2", x, perl=TRUE)
## => [1] "cat dog" "dog cat"
要在不匹配的情况下返回
NA
,请使用正则表达式来匹配特定模式或整个字符串,并将其与gsubfn
一起使用以应用自定义替换逻辑:> gsubfn("^(?:.*((dog).*(giraffe)|(giraffe).*(dog)).*|.*)$", function(x,a,b,y,z,i) ifelse(nchar(x)>0, paste0(a,y," ",b,z), NA), x)
[1] "NA" "NA"
> gsubfn("^(?:.*((dog).*(cat)|(cat).*(dog)).*|.*)$", function(x,a,b,y,z,i) ifelse(nchar(x)>0, paste0(a,y," ",b,z), NA), x)
[1] "cat dog" "dog cat"
这里,
^
-字符串anchor的开头(?:.*((dog).*(cat)|(cat).*(dog)).*|.*)
-与两个备选方案之一匹配的non-capturing group:.*((dog).*(cat)|(cat).*(dog)).*
:.*
-尽可能多的0个字符((dog).*(cat)|(cat).*(dog))
-匹配两个替代项之一的capturing group:(dog).*(cat)
-dog
(组2,分配给a
变量),尽可能多的0个字符,然后cat
(组3,分配给b
变量)|
(cat).*(dog)
-dog
(组4,分配给y
变量),尽可能多的0个字符,然后cat
(组5,分配给z
变量).*
-尽可能多的0个字符|
-或.*
-任意0个以上的字符$
-字符串anchor的结尾。匿名函数中的
x
表示第1组的值是“技术性”,我们用nchar
检查第1组的匹配长度是否不为零,如果不为空,则用自定义逻辑替换,如果组1为空,则用NA
代替。关于r - 任意提取2个单词,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48591261/