14

我已经搜索并能够找到这个论坛讨论以实现重叠匹配的效果。

我还发现了以下关于查找索引以执行此任务的SO问题,但无法找到任何关于在 R 语言中获取重叠匹配项的简明信息。

我可以在大多数支持 ( PCRE ) 的语言中执行此任务,方法是使用 Positive Lookahead 断言,同时在前瞻内部实现捕获组以捕获重叠匹配。

但是,虽然实际上以我在其他语言中使用perl=TR 的相同方式执行此操作,但没有产生任何结果。

> x <- 'ACCACCACCAC'
> regmatches(x, gregexpr('(?=([AC]C))', x, perl=T))[[1]]
[1] "" "" "" "" "" "" ""

使用stringistringr包也是如此。

> library(stringi)
> library(stringr)
> stri_extract_all_regex(x, '(?=([AC]C))')[[1]]
[1] "" "" "" "" "" "" ""
> str_extract_all(x, perl('(?=([AC]C))'))[[1]]
[1] "" "" "" "" "" "" ""

执行此操作时应返回的正确结果是:

[1] "AC" "CC" "AC" "CC" "AC" "CC" "AC"

编辑

  1. 我很清楚这regmatches不适用于捕获的匹配,但究竟是什么导致了正则匹配中的这种行为,为什么没有返回结果?我正在寻找一个有点详细的答案

  2. stringiandstringr包不能执行此操作吗regmatches

  3. 请随时添加到我的答案中或提出与我发现不同的解决方法。

4

6 回答 6

7

至于解决方法,这就是我想出的提取重叠匹配的方法。

> x <- 'ACCACCACCAC'
> m <- gregexpr('(?=([AC]C))', x, perl=T)
> mapply(function(X) substr(x, X, X+1), m[[1]])
[1] "AC" "CC" "AC" "CC" "AC" "CC" "AC"

请随时添加或评论执行此任务的更好方法。

于 2014-09-12T02:56:48.267 回答
7

该标准regmatches不适用于捕获的匹配项(特别是同一字符串中的多个捕获匹配项)。在这种情况下,由于您正在“匹配”前瞻(忽略捕获),因此匹配本身的长度为零。还有一个regmatches()<-函数可以说明这一点。观察

x <- 'ACCACCACCAC'
m <- gregexpr('(?=([AC]C))', x, perl=T)
regmatches(x, m) <- "~"
x
# [1] "~A~CC~A~CC~A~CC~AC"

注意所有字母是如何被保留的,我们刚刚用我们可以观察到的东西替换了零长度匹配的位置。

我创建了一个经常用于此类任务的regcapturedmatches()函数。例如

x <- 'ACCACCACCAC'
regcapturedmatches(x, gregexpr('(?=([AC]C))', x, perl=T))[[1]]

#      [,1] [,2] [,3] [,4] [,5] [,6] [,7]
# [1,] "AC" "CC" "AC" "CC" "AC" "CC" "AC"

可以很好地gregexpr抓取所有数据,因此如果您不想使用此辅助函数,您可以从该对象中提取它。

于 2014-09-12T03:37:15.950 回答
5

stringi在前瞻部分使用捕获组的解决方案:

> stri_match_all_regex('ACCACCACCAC', '(?=([AC]C))')[[1]][,2]
## [1] "AC" "CC" "AC" "CC" "AC" "CC" "AC"    
于 2014-10-26T19:55:05.707 回答
4

提取我过去所做的相同信息的另一种迂回方法是将 替换"match.length""capture.length"

x <- c("ACCACCACCAC","ACCACCACCAC")
m <- gregexpr('(?=([AC]C))', x, perl=TRUE)
m <- lapply(m, function(i) {
       attr(i,"match.length") <- attr(i,"capture.length")
       i
     })
regmatches(x,m)

#[[1]]
#[1] "AC" "CC" "AC" "CC" "AC" "CC" "AC"
#
#[[2]]
#[1] "AC" "CC" "AC" "CC" "AC" "CC" "AC"
于 2014-09-12T05:10:21.853 回答
4

这不是一个正则表达式解决方案,并不能真正回答您的任何更重要的问题,但您也可以通过一次使用两个字符的子字符串然后删除不需要的CA元素来获得所需的结果。

x <- 'ACCACCACCAC'
y <- substring(x, 1:(nchar(x)-1), 2:nchar(x))
y[y != "CA"]
# [1] "AC" "CC" "AC" "CC" "AC" "CC" "AC"
于 2014-09-13T02:54:47.370 回答
1

另一个答案,基于@hwnd 自己的答案(原版不允许可变长度捕获区域),仅使用内置 R 函数:

> x <- 'ACCACCACCAC'
> m <- gregexpr('(?=([AC]C))', x, perl=T)[[1]]
> start <- attr(m,"capture.start")
> end <- attr(m,"capture.start") + attr(m,"capture.length") - 1
> sapply(seq_along(m), function(i) substr(x, start[i], end[i]))
[1] "AC" "CC" "AC" "CC" "AC" "CC" "AC"

非常丑陋,这就是stringretc. 包存在的原因。

于 2015-08-10T14:51:07.290 回答