获取r中字符串中模式的重叠位置

获取r中字符串中模式的重叠位置,r,regex,R,Regex,目标: 在允许重叠的字符串中查找模式的所有位置(开始和结束索引) 方法: stri\u locate\u all.*函数返回字符串中模式的位置列表。该列表包括包含每个匹配位置的开始索引和结束索引的矩阵。这对我来说很方便 对于固定模式,以下操作非常有效: s <- "---" pattern <- "--" stri_locate_all_fixed(s, pattern, overlap = TRUE) [[1]] start en

目标:

在允许重叠的字符串中查找模式的所有位置(开始和结束索引)

方法:

stri\u locate\u all.*
函数返回字符串中模式的位置列表。该列表包括包含每个匹配位置的开始索引和结束索引的矩阵。这对我来说很方便

对于固定模式,以下操作非常有效:

s <- "---"
pattern <- "--"
stri_locate_all_fixed(s, pattern, overlap = TRUE)
[[1]]
    start   end
[1,]    1   2
[1,]    2   3
请注意,
stri\u locate\u all\u regex
不使用重叠属性,因此如果要捕获重叠,必须调整模式

根据各种来源,我需要为我的正则表达式添加一个积极的前瞻

pattern <- "(?=[1|-]{2})"
在这里,函数正确地识别出存在两个匹配项,并注意到开始索引,但结束索引低于开始索引

各国:

“对于stri_locate_*_正则表达式,如果匹配长度为0,则end将为1 字符数小于“开始”

这表明匹配的长度为0;这一观察结果得到以下方面的进一步支持:

“向前看和向后看,统称为“环顾”,是 长度为零的断言…查找实际上与字符匹配, 但随后放弃匹配,只返回结果:匹配或否 匹配。”

因此,我的问题似乎在于使用正向前瞻断言,该断言似乎在“开始”索引处返回零长度位置

我提炼的问题:

-是否有更好的regexp方法来捕获重叠(非零长度)匹配?或者

-是否有比stri\u locate\u all\u regex更好的r函数来实现所需的输出(字符串中模式匹配的所有开始/结束位置的列表)


谢谢

您可以使用
gregexpr
和带有捕获组的PCRE正则表达式,捕获组包含整个正向前瞻模式:

pattern <- "(?=([1-]{2}))"
s <- "-1-"
res <- gregexpr(pattern, s, perl=TRUE)
starts <- attr(res[[1]],'capture.start') 
lengths <- attr(res[[1]],'capture.length')
ends <- starts + lengths - 1
df_positions <- do.call(rbind, Map(data.frame, start=starts, end=ends, length=lengths))
df_positions

查看一个

您可以使用
gregexpr
和一个带有捕获组的PCRE正则表达式,捕获组包含整个正向前瞻模式:

pattern <- "(?=([1-]{2}))"
s <- "-1-"
res <- gregexpr(pattern, s, perl=TRUE)
starts <- attr(res[[1]],'capture.start') 
lengths <- attr(res[[1]],'capture.length')
ends <- starts + lengths - 1
df_positions <- do.call(rbind, Map(data.frame, start=starts, end=ends, length=lengths))
df_positions

查看一个

您可以使用lookback重复搜索,然后将两个结果合并。在函数内部,它不会弄乱代码,但可能有点低效:

library(stringi)

stri_locate_overlap <- function(str, pattern) {
  s <- stri_locate_all_regex(str, paste0("(?=", pattern, ")")) # match start, length 0
  e <- stri_locate_all_regex(str,  paste0("(?<=", pattern, ")")) # match end, length 0
  # combine two results
  mapply(function(x, y) {
    data.frame(start = x[, 1], 
               end = y[, 1])
  }, x = s, y = e, SIMPLIFY = FALSE)
}

stri_locate_overlap(c("---", "-1-"), "[1|-]{2}")
#> [[1]]
#>   start end
#> 1     1   3
#> 2     2   4
#> 
#> [[2]]
#>   start end
#> 1     1   3
#> 2     2   4
库(stringi)
stri_定位_重叠1 1 3
#> 2     2   4
#> 
#> [[2]]
#>起始端
#> 1     1   3
#> 2     2   4

您可以使用lookback重复搜索,然后将两个结果合并。在函数内部,它不会弄乱代码,但可能有点低效:

library(stringi)

stri_locate_overlap <- function(str, pattern) {
  s <- stri_locate_all_regex(str, paste0("(?=", pattern, ")")) # match start, length 0
  e <- stri_locate_all_regex(str,  paste0("(?<=", pattern, ")")) # match end, length 0
  # combine two results
  mapply(function(x, y) {
    data.frame(start = x[, 1], 
               end = y[, 1])
  }, x = s, y = e, SIMPLIFY = FALSE)
}

stri_locate_overlap(c("---", "-1-"), "[1|-]{2}")
#> [[1]]
#>   start end
#> 1     1   3
#> 2     2   4
#> 
#> [[2]]
#>   start end
#> 1     1   3
#> 2     2   4
库(stringi)
stri_定位_重叠1 1 3
#> 2     2   4
#> 
#> [[2]]
#>起始端
#> 1     1   3
#> 2     2   4

解决方案的有趣想法。我很好奇为什么末端位置在索引范围之外(长度是3而不是2)。我认为lookback遍历最后一个字符以找到字符串的结尾,然后从那里向后工作,因此必须从结束值中减去一个。解决方法的有趣想法。我很好奇为什么末端位置在索引范围之外(长度是3而不是2)。我认为lookback遍历最后一个字符以找到字符串的结尾,然后从那里向后工作,因此必须从结束值中减去一。
library(stringi)

stri_locate_overlap <- function(str, pattern) {
  s <- stri_locate_all_regex(str, paste0("(?=", pattern, ")")) # match start, length 0
  e <- stri_locate_all_regex(str,  paste0("(?<=", pattern, ")")) # match end, length 0
  # combine two results
  mapply(function(x, y) {
    data.frame(start = x[, 1], 
               end = y[, 1])
  }, x = s, y = e, SIMPLIFY = FALSE)
}

stri_locate_overlap(c("---", "-1-"), "[1|-]{2}")
#> [[1]]
#>   start end
#> 1     1   3
#> 2     2   4
#> 
#> [[2]]
#>   start end
#> 1     1   3
#> 2     2   4