在R中的其他两个字符串之间提取一个字符串

Extracting a string between other two strings in R

我正在尝试找到一种简单的方法来提取出现在两个已知子字符串之间的未知子字符串(可以是任何内容)。例如,我有一个字符串:

a<-" anything goes here, STR1 GET_ME STR2, anything goes here"

我需要提取字符串 GET_ME,它位于 STR1 和 STR2 之间(没有空格)。

我正在尝试 str_extract(a, "STR1 (.+) STR2"),但我得到了整场比赛

[1] "STR1 GET_ME STR2"

我当然可以剥离已知的字符串,以隔离我需要的子字符串,但我认为应该有一种更简洁的方法来使用正确的正则表达式来做到这一点。

您可以将 str_matchSTR1 (.*?) STR2 一起使用(注意空格是“有意义的”,如果您只想匹配 STR1STR2 之间的任何内容,请使用 STR1(.*?)STR2,或使用 STR1\s*(.*?)\s*STR2 到 trim 您需要的值)。如果多次出现,请使用 str_match_all.

此外,如果您需要匹配跨越行 breaks/newlines 的字符串,请在模式的开头添加 (?s)(?s)STR1(.*?)STR2 / (?s)STR1\s*(.*?)\s*STR2.

library(stringr)
a <- " anything goes here, STR1 GET_ME STR2, anything goes here"
res <- str_match(a, "STR1\s*(.*?)\s*STR2")
res[,2]
[1] "GET_ME"

另一种使用基数 R regexec 的方法(获得第一个匹配项):

test <- " anything goes here, STR1 GET_ME STR2, anything goes here STR1 GET_ME2 STR2"
pattern <- "STR1\s*(.*?)\s*STR2"
result <- regmatches(test, regexec(pattern, test))
result[[1]][2]
[1] "GET_ME"

这是使用基数 R 的另一种方法

a<-" anything goes here, STR1 GET_ME STR2, anything goes here"

gsub(".*STR1 (.+) STR2.*", "\1", a)

输出:

[1] "GET_ME"

另一种选择是使用qdapRegex::ex_between提取左右边界之间的字符串

qdapRegex::ex_between(a, "STR1", "STR2")[[1]]
#[1] "GET_ME"

它也适用于多次出现

a <- "anything STR1 GET_ME STR2, anything goes here, STR1 again get me STR2"

qdapRegex::ex_between(a, "STR1", "STR2")[[1]]
#[1] "GET_ME"       "again get me"

或者多个左右边界

a <- "anything STR1 GET_ME STR2, anything goes here, STR4 again get me STR5"
qdapRegex::ex_between(a, c("STR1", "STR4"), c("STR2", "STR5"))[[1]]
#[1] "GET_ME"       "again get me"

第一次捕获在 "STR1" 和 "STR2" 之间,而第二次捕获在 "STR4" 和 "STR5" 之间。

我们可以使用 {unglue},在那种情况下我们根本不需要正则表达式:

library(unglue)
unglue::unglue_vec(
  " anything goes here, STR1 GET_ME STR2, anything goes here", 
  "{}STR1 {x} STR2{}")
#> [1] "GET_ME"

{} 匹配任何内容而不保留它,{x} 捕获它的匹配项(可以使用 x 以外的任何变量。语法 "{}STR1 {x} STR2{}" 是 : "{=.*?}STR1 {x=.*?} STR2{=.*?}"

如果你也想提取边,你可以这样做:

unglue::unglue_data(
  " anything goes here, STR1 GET_ME STR2, anything goes here", 
  "{left}, STR1 {x} STR2, {right}")
#>                  left      x              right
#> 1  anything goes here GET_ME anything goes here