正则表达式如何不止一次匹配捕获组

时间:2017-04-20 09:25:44

标签: regex

我有以下正则表达式:

\{(\w+)(?:\{(\w+))+\}+\}

我需要它来匹配以下任何一个

{a{b}}

{a{b{c}}}

{a{b{c{d...}}}}

但是通过在最后一个上使用正则表达式,它只匹配两个组:ac它不匹配b和' c& #39;或其他任何可能介于两者之间的词语。

如何让小组匹配每个小组,如:

group #1: a
group #2: b
group #3: c
group #4: d
group #4: etc...

或喜欢

group #1: a
group #2: [b, c, d, etc...]

另外,我如何制作它以使左侧{的数量相同,右侧有},否则不匹配?

感谢您的帮助,

大卫

2 个答案:

答案 0 :(得分:2)

在.NET中,正则表达式可以1)检查平衡组,2)为组堆栈中的每个捕获组存储捕获集合。

如果以{开头且以}结尾的整个字符串包含以下正则表达式,则您可以仅提取每个^{(?:(?<c>[^{}]+)|(?<o>){|(?<-o>)})*(?(o)(?!))}$ 中的所有文本平衡量的那些开/关花括号:

^

请参阅regex demo

<强>详情:

  • { - 字符串开头
  • (?: - 一个大括号
  • (?<c>[^{}]+) - 开始一组替代方案:
    • { - 除了}|以外的1个字符被捕获到&#34; c&#34;组
    • (?<o>{) - 或
    • { - |匹配,并将值推送到组&#34; o&#34;堆
    • (?<-o>}) - 或
    • } - 匹配)*并从Group&#34; o&#34;中弹出一个值堆
  • (?(o)(?!)) - 交替小组结束,重复0次以上
  • } - 一个条件构造,检查Group&#34; o&#34;堆栈是空的
  • } - 关闭$
  • var pattern = "^{(?:(?<c>[^{}]+)|(?<o>{)|(?<-o>}))*(?(o)(?!))}$"; var result = Regex.Matches("{a{bb{ccc{dd}}}}", pattern) .Cast<Match>().Select(p => p.Groups["c"].Captures) .ToList(); - 字符串结束。

C# demo

{a{bb{ccc{dd}}}}

[a, bb, ccc, dd]的输出为{{a{bb{ccc{dd}}}}{的输出(开头添加了{{1}}),结果为空。

答案 1 :(得分:2)

对于支持递归的正则表达式(PCRE,Ruby),您可以使用以下通用模式:

^({\w+(?1)?})$

它允许检查输入matches the defined pattern但是不捕获所需的组。有关详细信息,请参阅http://www.regular-expressions.info/recurse.html中的匹配均衡结构部分。

为了捕获组,我们可以将模式检查正则表达式转换为正向前导,在字符串((?:^(?=({\w+(?1)?})$)|\G(?!\A)))的开头只检查一次,然后使用全局搜索捕获所有“单词”:

(?:^(?=({\w+(?1)?})$)|\G(?!\A)){(\w+)

abc等现在位于第二个捕获组中。

正则表达式演示:https://regex101.com/r/2wsR10/2。 PHP演示:https://ideone.com/UKTfcm

<强>解释

  • (?: - 交替小组的开始
    • [第一种选择]:
      • ^ - 字符串开头
      • (?= - 开始积极向前看
      • ({\w+(?1)?}) - 上面的通用模式
      • $ - 字符串的enf
      • ) - 结束了积极向前看
    • | - 或
    • [第二种选择]:
      • \G - end of previous match
      • (?!\A) - 如果第一个选项失败,请确保之前的\G与输入的开头不匹配
  • ) - 交替小组结束
  • { - 按字面意思打开大括号
  • (\w+) - 在第二组中捕获的“字”。

Ruby有不同的递归语法,正则表达式是:

(?:^(?=({\w+\g<1>?})$)|\G(?!\A)){(\w+)

演示:http://rubular.com/r/jOJRhwJvR4