正则表达式 - 捕获排除周围部分匹配内容的重复组

Regex - Capturing repeating groups excluding surrounding partially matching content

郑重声明,我使用的是 R,但我的查询与平台无关(就目前而言),因此我将使用 regex101 进行演示。我试图捕捉重复的组,这些组可能会或可能不会被其他文本包围。所以理想的行为显示在这个演示中: demo1

正则表达式:(\d{2})(AB)

文本:blahblah11AB12AB13ABblah

所以它很好地捕获了我想要的所有组:

匹配 1

Full match  8-12    `11AB`
Group 1.    8-10    `11`
Group 2.    10-12   `AB`

匹配 2

Full match  12-16   `12AB`
Group 1.    12-14   `12`
Group 2.    14-16   `AB`

匹配 3

Full match  16-20   `13AB`
Group 1.    16-18   `13`
Group 2.    18-20   `AB`

但是,如果我包含另一段匹配的文本,它也会捕获该文本(我想这很公平)

正文:blahblah11AB12AB13ABblah22AB returns 相同,但多了一个组:

匹配 4

Full match  24-28   `22AB`
Group 1.    24-26   `22`
Group 2.    26-28   `AB`

demo2

我想做的是捕获第一组但忽略所有其他文本,即使有后续匹配项也是如此。本质上,我只想从这个文本中获得三个匹配项:blahblah11AB12AB13ABblah22AB

我试过很多东西,比如这个: (((\d{2})(AB))+)(.*)

但后来我得到了以下内容,它丢失了最后一组捕获的所有内容:

Demo 3

匹配 1

Full match  8-28    `11AB12AB13ABblah22AB`
Group 1.    8-20    `11AB12AB13AB`
Group 2.    16-20   `13AB`
Group 3.    16-18   `13`
Group 4.    18-20   `AB`
Group 5.    20-28   `blah22AB`

我需要保留重复组的东西。我很难过!

在 R 中,输出应如下所示:

[[1]]
     [,1]   [,2] [,3]
[1,] "11AB" "11" "AB"
[2,] "12AB" "12" "AB"
[3,] "13AB" "13" "AB"

提前致谢...

如果我没理解错的话,问题出在括号的位置上。

pattern <- "(\d{2}AB)"

s <- "blahblah11AB12AB13ABbla"

m <- gregexpr(pattern, s)
regmatches(s, m)
#[[1]]
#[1] "11AB" "12AB" "13AB"


s2 <- "blahblah11AB12AB13ABblah22AB"
s3 <- "11AB12AB13ABblah22AB"

S <- c(s, s2, s3)

m <- gregexpr(pattern, S)
regmatches(S, m)
#[[1]]
#[1] "11AB" "12AB" "13AB"
#
#[[2]]
#[1] "11AB" "12AB" "13AB" "22AB"
#
#[[3]]
#[1] "11AB" "12AB" "13AB" "22AB"

请注意,很多时候这只是一个代码行中的 运行。为了更清楚,我将其保留为这样。

编辑。

也许以下内容满足了 OP 的要求。
我敢打赌有更好的解决方案,在我看来,两个正则表达式是一种矫枉过正。

pattern <- "((\d{2}AB)+)([^[:digit:]AB]+(\d{2}AB))"
pattern2 <- "(\d{2}AB)"

m <- gregexpr(pattern2, gsub(pattern, "\1", S))
regmatches(S, m)
#[[1]]
#[1] "11AB" "12AB" "13AB"
#
#[[2]]
#[1] "11AB" "12AB" "13AB"
#
#[[3]]
#[1] "11AB" "12AB" "13AB"

您可以使用量词 {3} 来获得前 3 个组:(((\d{2})(AB)){3})。参见 demo

一个想法会在 use \G for chaining matches to ^ start and reset by \K 之后。

(?:^.*?\K|\G)(\d{2})(AB)
  • ^.*?\K 将在第一次匹配之前延迟匹配任意数量的任意字符
  • |\G 或在上一场比赛结束时继续,可以是:开始、第一、上一场

See your updated demo

这将匹配第一个匹配链并且是一个 pcre 模式 (perl=TRUE)。
如果在第一个匹配之前只能有非数字,use ^\D*\K instead of ^.*?\K.