【问题标题】:regex match on R gregexprR gregexpr 上的正则表达式匹配
【发布时间】:2013-01-22 04:16:45
【问题描述】:

我正在尝试计算 3 个连续“a”事件的实例,"aaa"

字符串将包含较低的字母,例如"abaaaababaaa"

我尝试了以下代码。但这种行为并不是我想要的。

x<-"abaaaababaaa";
gregexpr("aaa",x);

我希望匹配返回 3 个“aaa”实例,而不是 2 个。

假设索引从 1 开始

  • “aaa”的第一次出现在索引 3 处。
  • “aaa”的第二次出现在索引 4 处。(这未被 gregexpr)
  • “aaa”第三次出现在索引 10 处。

【问题讨论】:

    标签: regex string r


    【解决方案1】:

    要捕获重叠匹配,您可以使用如下的前瞻:

    gregexpr("a(?=aa)", x, perl=TRUE)
    

    但是,您的匹配现在只是一个“a”,因此可能会使这些匹配的进一步处理变得复杂,尤其是当您并不总是寻找固定长度的模式时。

    【讨论】:

      【解决方案2】:

      我知道我迟到了,但我想分享这个解决方案,

      your.string <- "abaaaababaaa"
      nc1 <- nchar(your.string)-1
      x <- unlist(strsplit(your.string, NULL))
      x2 <- c()
      for (i in 1:nc1)
      x2 <- c(x2, paste(x[i], x[i+1], x[i+2], sep="")) 
      cat("ocurrences of <aaa> in <your.string> is,", 
          length(grep("aaa", x2)), "and they are at index", grep("aaa", x2))
      > ocurrences of <aaa> in <your.string> is, 3 and they are at index 3 4 10
      

      受到来自 R-help by Fran 的 this answer 的极大启发。

      【讨论】:

      • 这也能完成这项工作(投票赞成),但我想避免显式循环,我的字符串很长。
      • @AdityaSihag,它绝对可以优化,我只是想把这个解决方案也扔进去。
      【解决方案3】:

      这是一种使用 gregexpr 提取所有不同长度的重叠匹配的方法。

      x<-"abaaaababaaa"
      # nest in lookahead + capture group
      # to get all instances of the pattern "(ab)|b"
      matches<-gregexpr('(?=((ab)|b))', x, perl=TRUE)
      # regmatches will reference the match.length attr. to extract the strings
      # so move match length data from 'capture.length' to 'match.length' attr
      attr(matches[[1]], 'match.length') <- as.vector(attr(matches[[1]], 'capture.length')[,1])
      # extract substrings
      regmatches(x, matches)
      # [[1]]
      # [1] "ab" "b"  "ab" "b"  "ab" "b" 
      

      诀窍是将模式包围在一个捕获组中,并将该捕获组包围在一个前瞻断言中。 gregexpr 将返回一个列表,其中包含具有属性capture.length 的起始位置,其中第一列是第一个捕获组的匹配长度的矩阵。如果将其转换为向量并将其移动到 match.length 属性中(全为零,因为整个模式都在前瞻断言中),则可以将其传递给 regmatches 以提取字符串。

      正如最终结果的类型所暗示的那样,经过一些修改,这可以向量化,对于 x 是字符串列表的情况。

      x<-list(s1="abaaaababaaa", s2="ab")
      matches<-gregexpr('(?=((ab)|b))', x, perl=TRUE)
      # make a function that replaces match.length attr with capture.length
      set.match.length<-
      function(x) structure(x, match.length=as.vector(attr(x, 'capture.length')[,1]))
      # set match.length to capture.length for each match object
      matches<-lapply(matches, set.match.length)
      # extract substrings
      mapply(regmatches, x, lapply(matches, list))
      # $s1
      # [1] "ab" "b"  "ab" "b"  "ab" "b" 
      # 
      # $s2
      # [1] "ab" "b" 
      

      【讨论】: