Regex R:提取两个子字符串之间包含的所有子字符串的最快方法

Regex R:提取两个子字符串之间包含的所有子字符串的最快方法,regex,r,string,substring,Regex,R,String,Substring,我正在寻找一种有效的方法来提取字符串中两个子字符串之间的所有匹配项。例如,假设我想提取字符串之间包含的所有子字符串 start="strt" 及 我想要向量 "111" "222" 在R中最有效的方法是什么?也许使用正则表达式?或者有更好的方法吗?由于每个输入可以有几个开始/停止字符串,我认为正则表达式将是最有效的解决方案: (?<=strt)(?:(?!stp).)* 对于像这样简单的事情,base R处理得很好 您可以通过使用perl=T和使用断言来打开 x <- 'str

我正在寻找一种有效的方法来提取字符串中两个子字符串之间的所有匹配项。例如,假设我想提取字符串之间包含的所有子字符串

start="strt"

我想要向量

"111" "222"

在R中最有效的方法是什么?也许使用正则表达式?或者有更好的方法吗?

由于每个输入可以有几个开始/停止字符串,我认为正则表达式将是最有效的解决方案:

(?<=strt)(?:(?!stp).)*

对于像这样简单的事情,base R处理得很好

您可以通过使用
perl=T
和使用断言来打开

x <- 'strt111stpblablastrt222stp'
regmatches(x, gregexpr('(?<=strt).*?(?=stp)', x, perl=T))[[1]]
# [1] "111" "222"
你也可以考虑:

library(qdap)
unname(genXtract(x, "strt", "stp"))
#[1] "111" "222"
速度比较

 x1 <- rep(x,1e5)
 system.time(res1 <- regmatches(x1,gregexpr('(?<=strt).*?(?=stp)',x1,perl=T)))
 #   user  system elapsed 
 #  2.187   0.000   2.015 

 system.time(res2 <- regmatches(x1, gregexpr("(?<=strt)(?:(?!stp).)*", x1, perl=TRUE)))
 #user  system elapsed 
 #  1.902   0.000   1.780 

 system.time(res3 <- str_extract_all(x1, perl('(?<=strt).*?(?=stp)')))
 # user  system elapsed 
 #  6.990   0.000   6.636 

 system.time(res4 <- genXtract(x1, "strt", "stp")) ##setNames(genXtract(...), NULL) is a bit slower
 # user  system elapsed 
 # 1.457   0.000   1.414 

 names(res4) <- NULL
identical(res1,res4)
#[1] TRUE

x1如果您谈论的是R字符串中的速度,那么只有一个包可以做到这一点-


x许多thx-这是完美的,thx是非常好的解释+1,作为补充,我将提到
strt\K
可以取代
(?Thx用于额外稍快的选项-这很好!!我预计
genXtract
会慢很多(慢10-20倍)。它是为灵活性和易用性而构建的。在许多情况下,研究人员的时间比计算时间更有价值。如果是这样的话,
genXtract
是一个很好的选择。如果你追求速度,那么我和你一样,都是
stringi
的超级粉丝。我不仅仅是
stringi
粉丝——我是一名作家:)
perl已被弃用,请改用regex
,我不想编辑答案,因为从那时起基准测试结果可能已经发生了变化。
(?<=          # look behind to see if there is:
  strt        #   'strt'
)             # end of look-behind
.*?           # any character except \n (0 or more times)
(?=           # look ahead to see if there is:
  stp         #   'stp'
)             # end of look-ahead
library(stringi)
x <- 'strt111stpblablastrt222stp'
stri_extract_all_regex(x, '(?<=strt).*?(?=stp)')[[1]]
# [1] "111" "222"
library(qdapRegex)
x <- 'strt111stpblablastrt222stp'
rm_between(x, 'strt', 'stp', extract=TRUE)[[1]]
# [1] "111" "222"
library(qdap)
unname(genXtract(x, "strt", "stp"))
#[1] "111" "222"
 x1 <- rep(x,1e5)
 system.time(res1 <- regmatches(x1,gregexpr('(?<=strt).*?(?=stp)',x1,perl=T)))
 #   user  system elapsed 
 #  2.187   0.000   2.015 

 system.time(res2 <- regmatches(x1, gregexpr("(?<=strt)(?:(?!stp).)*", x1, perl=TRUE)))
 #user  system elapsed 
 #  1.902   0.000   1.780 

 system.time(res3 <- str_extract_all(x1, perl('(?<=strt).*?(?=stp)')))
 # user  system elapsed 
 #  6.990   0.000   6.636 

 system.time(res4 <- genXtract(x1, "strt", "stp")) ##setNames(genXtract(...), NULL) is a bit slower
 # user  system elapsed 
 # 1.457   0.000   1.414 

 names(res4) <- NULL
identical(res1,res4)
#[1] TRUE
 x <- "strt111stpblablastrt222stp"
 hwnd <- function(x1) regmatches(x1,gregexpr('(?<=strt).*?(?=stp)',x1,perl=T))
 Tim <- function(x1) regmatches(x1, gregexpr("(?<=strt)(?:(?!stp).)*", x1, perl=TRUE))
 stringr <- function(x1) str_extract_all(x1, perl('(?<=strt).*?(?=stp)'))
 akrun <- function(x1) genXtract(x1, "strt", "stp")
 stringi <- function(x1) stri_extract_all_regex(x1, perl('(?<=strt).*?(?=stp)'))

 require(microbenchmark)
 microbenchmark(stringi(x), hwnd(x), Tim(x), stringr(x))
Unit: microseconds
       expr     min       lq  median       uq     max neval
 stringi(x)  46.778  58.1030  64.017  67.3485 123.398   100
    hwnd(x)  61.498  73.1095  79.084  85.5190 111.757   100
     Tim(x)  60.243  74.6830  80.755  86.3370 102.678   100
 stringr(x) 236.081 261.9425 272.115 279.6750 440.036   100