【问题标题】:REGEX Capturing differing sets of repeating groupsREGEX 捕获不同组的重复组
【发布时间】:2018-08-21 20:43:10
【问题描述】:

这是一个由两部分组成的问题,但我觉得答案是相关的。

我有这个正则表达式模式: (\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`

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

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` 

另外,我想做类似的事情,但将“或”组翻转到最后,即:

1cc2cc3cc4cc5cc6cc7ccb8aa9bb

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

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

有什么想法吗?

【问题讨论】:

  • 那么,试过(\d+)(aa|bb|cc)?
  • 是的,这在技术上确实捕获了它,但我不希望所有三个字符串的随机“或”。我想要一系列 aa bb 组合然后是一个 cc 组(或只是一个 cc)。而且,大概使用不同的正则表达式模式,一系列 cc,然后是一些 aa bb 组合。这有意义吗?
  • 对不起,我不明白你的意思。另外,请将正则表达式 falvor 标签添加到问题中。
  • 只是不要说“我需要让它在 regex101.com 上工作,然后我会在 C# 应用程序中使用它”。有些人编写 PCRE,然后尝试在 Python re 中使用正则表达式。真的,这很可悲。
  • 您可以使用this 查找任意数量的 xaa 或 xbb 匹配,然后是任意数量的 xcc 匹配。如您所见,如果不满足此模式,则它不匹配。然后,您可以使用 Wiktor 的模式将其分解为捕获组。

标签: regex pcre repeat


【解决方案1】:

你可以使用

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

见regex demo

正则表达式只会匹配满足(?=(?:\d+(?:aa|bb))+(?:\d+cc)+)前瞻中模式的字符串,然后会连续匹配并捕获数字和aa、bb或cc,但数字+aa或@ 987654332@ 将被匹配,除非数字 + cc 不在前面。

详情

  • (?:\G(?!^)(?(?=\d+(?:aa|bb))(?&lt;!\dcc))|(?=(?:\d+(?:aa|bb))+(?:\d+cc)+)) - 两种选择之一:
    • \G(?!^) - 上一次成功匹配结束
    • (?(?=\d+(?:aa|bb))(?&lt;!\dcc)) - if-then-else 构造:如果有 1+ 个数字,并且在当前位置(bb)的右侧紧邻当前位置((?=\d+(?:aa|bb)),则仅在后面没有数字时才继续匹配cc 紧邻当前位置的左侧 ((?&lt;!\dcc))
    • | - 或
    • ^ - 字符串开头
    • (?=(?:\d+(?:aa|bb))+(?:\d+cc)+) - 一个积极的前瞻,在当前位置的右侧,搜索以下内容(如果找到模式则返回 true,否则返回 false):
      • (?:\d+(?:aa|bb))+ - 出现一个或多个 1+ 数字后跟 aa 或 bb
      • (?:\d+cc)+ - 出现一个或多个 1+ 数字后跟 cc
  • (\d+) - 第 1 组:一位或多位数字
  • (aa|bb|cc) - aa、bb 或 cc。

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

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

【讨论】:

  • 当天网接管时,我的钱花在了 Wiktor 通过创建一个导致其 CPU 过热的恶意正则表达式模式来拯救人类。我每天都从你那里学到新东西。
  • @emsimpson92 我怀疑正则表达式是否能够做到这一点,因为它只对 text 数据进行操作,但要引起灾难性的回溯,并不需要真正了解正则表达式.我想反之亦然:) 我修正了我对前瞻的描述。
  • 感谢您为此所做的工作。你几乎破解了它。但是,该字符串将成为更大字符串的一部分。在您的解决方案中,如果我们最后添加任何内容,它将不匹配,例如link这里我添加了一个X。对不起,如果我没有指定。
  • @Funtboy 这不是问题,remove $ in the lookahead。 $ 需要字符串结尾。
  • 如果您还想在系列之前允许文本,这将是完整的解决方案:(?:\G(?!^)|(?=(?:\d+(?:aa|bb))+(?:\d+cc)+))(\d+)(aa|bb|cc)
【解决方案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);
}

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

【讨论】:

  • 是的,你好,如上所述,我不想混合 cc 和 aa bb 组合。一个系列必须跟随另一个。我意识到我正在寻找两种不同的正则表达式模式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-31
  • 2019-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多