REGEX 捕获不同的重复组集

REGEX Capturing differing sets of repeating groups

这是一个分为两部分的问题,但我觉得答案会有关联。

我有这个正则表达式模式: (\d+)(aa|bb) 我用它来捕获这个字符串:1bb2aa3aa4bb5bb6aa7bb8cc9cc

查看演示:example 1

它捕获 aa 和 bb(均以数字开头)的随机序列的方式正是我想要的,就目前而言是好的。

所以我们在 regex101 上得到了这个匹配:

Match 1
Full match  0-3 `1bb`
Group 1.    0-1 `1`
Group 2.    1-3 `bb`
Match 2
Full match  3-6 `2aa`
Group 1.    3-4 `2`
Group 2.    4-6 `aa`
Match 3
Full match  6-9 `3aa`
Group 1.    6-7 `3`
Group 2.    7-9 `aa`
Match 4
Full match  9-12    `4bb`
Group 1.    9-10    `4`
Group 2.    10-12   `bb`
Match 5
Full match  12-15   `5bb`
Group 1.    12-13   `5`
Group 2.    13-15   `bb`
Match 6
Full match  15-18   `6aa`
Group 1.    15-16   `6`
Group 2.    16-18   `aa`
Match 7
Full match  18-21   `7bb`
Group 1.    18-19   `7`
Group 2.    19-21   `bb`

正如预期的那样,最后的 8cc9cc 位被忽略了。我也想捕捉到这一点,就像我捕捉到第一个重复组一样,用同样的表达方式。所以在最终输出中,我会在输出末尾添加类似这样的内容。这应该适用于任何一方的任何数量的比赛。这篇文章只是一个例子。

Full match  21-24   `8cc`
Group 1.    21-22   `8`
Group 2.    22-24   `cc`
Match 7
Full match  24-27   `9cc`
Group 1.    24-25   `9`
Group 2.    25-27   `cc` 

此外,我想做类似的事情,但将 'or' 组翻转到最后,即:

1cc2cc3cc4cc5cc6cc7ccb8aa9bb

我当前的正则表达式模式 (\d+)(cc) 只匹配重复的 'cc' 组。 参见演示:example 2

我想要一个类似的完整捕获,每组允许的条目数量不限。

有什么想法吗?

我不是 perl 专家,所以我会在这里给出一些伪代码。欢迎提出修改建议。

您可以先匹配任意数量的 xaa 或 xbb 组合,然后使用此模式匹配一​​个或多个 xcc 组合:^(?:\d+(?:aa|bb))+(?:\dcc)+$

一旦你有了,你就可以使用这个模式来捕获适当的组:(\d+)(aa|bb|cc)

Demo 1

Demo 2

类似于:

if(ismatch("^(?:\d+(?:aa|bb))+(?:\dcc)+$", inputString))
{
  match = match("(\d+)(aa|bb|cc)", inputString);
}

从这里您可以使用组提取信息。

您可以使用

(?:\G(?!^)(?(?=\d+(?:aa|bb))(?<!\dcc))|(?=(?:\d+(?:aa|bb))+(?:\d+cc)+))(\d+)(aa|bb|cc)

regex demo

正则表达式只会匹配符合(?=(?:\d+(?:aa|bb))+(?:\d+cc)+) lookahead中的模式的字符串,然后会连续匹配捕获数字和aabbcc, 但数字 + aabb 将被匹配,除非数字 + cc 不在前面。

详情

  • (?:\G(?!^)(?(?=\d+(?:aa|bb))(?<!\dcc))|(?=(?:\d+(?:aa|bb))+(?:\d+cc)+)) - 两种选择之一:
    • \G(?!^) - 上一次成功匹配结束
    • (?(?=\d+(?:aa|bb))(?<!\dcc)) - if-then-else 构造:如果有 1+ 个数字并且 aabb 紧邻当前位置的右侧 ((?=\d+(?:aa|bb) ), 然后只有在当前位置 ((?<!\dcc))
    • 左边没有紧跟 cc 的数字时才继续匹配
    • | - 或
    • ^ - 字符串开头
    • (?=(?:\d+(?:aa|bb))+(?:\d+cc)+) - 正向前瞻,紧接在当前位置的右侧,搜索以下内容(returns 如果找到模式则为真,否则为假) :
      • (?:\d+(?:aa|bb))+ - 出现一次或多次 1+ 数字后跟 aabb
      • (?:\d+cc)+ - 出现一次或多次 1+ 数字后跟 cc
  • (\d+) - 第 1 组:一个或多个数字
  • (aa|bb|cc) - aabbcc.

对于第二个模式,replace cc with (?:aa|bb):

(?:\G(?!^)(?(?=\d+cc)(?<!\d(?:aa|bb)))|(?=(?:\d+cc)+(?:\d+(?:aa|bb))+))(\d+)(aa|bb|cc)