REGEX捕获不同组的重复组

时间:2018-08-21 20:43:10

标签: regex pcre repeat

这是一个分为两部分的问题,但是我认为答案将是相关的。

我有这个正则表达式模式: 我用来捕获此字符串的(\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

我想要一个类似的完整记录,每个组中允许有任何数量的条目。

有什么想法吗?

2 个答案:

答案 0 :(得分: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);
}

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

答案 1 :(得分:2)

您可以使用

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

请参见regex demo

正则表达式将仅匹配(?=(?:\d+(?:aa|bb))+(?:\d+cc)+)前瞻中符合模式的字符串,然后将连续匹配并捕获数字和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))的右侧,那么只有在当前位置(cc左边紧跟(?<!\dcc)后没有数字的情况下,才继续匹配。
    • |-或
    • ^-字符串的开头
    • (?=(?:\d+(?:aa|bb))+(?:\d+cc)+)-当前行右侧的正向搜索,搜索以下内容(如果找到模式,则返回true,否则,则返回false):
      • (?:\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)