【问题标题】:Regex Recursion: Nth Subpatterns正则表达式递归:第 N 个子模式
【发布时间】:2018-08-17 17:56:29
【问题描述】:

我正在尝试学习正则表达式中的递归,并对 PCRE 风格中的概念有一个基本的了解。我想断一个字符串:

Geese (Flock) Dogs (Pack) 

进入:

Full Match: Geese (Flock) Dogs (Pack) 
Group 1: Geese (Flock)
Group 2: Geese
Group 3: (Flock)
Group 4: Dogs (Pack)
Group 5: Dogs
Group 6: (Pack)

我知道这两个正则表达式都不能做到这一点,但我更好奇first 模式有效而second 无效的原因。

Pattern 1: ((.*?)(\(\w{1,}\)))((.*?)(\g<3>))*
Pattern 2: ((.*?)(\(\w{1,}\)))((\g<2>)(\g<3>))*

另外,例如,如果您正在处理一个长字符串,并且一个模式重复自身,是否可以不断扩展完整匹配,并逐步增加组,而无需编写与正则表达式分开的循环语句。

Full Match: Geese (Flock) Dogs (Pack) Elephants (Herd) 
Group 1: Geese (Flock)
Group 2: Geese
Group 3: (Flock)
Group 4: Dogs (Pack)
Group 5: Dogs
Group 6: (Pack)
Group 7: Elephants (Herd)
Group 8: Elephants 
Group 9: (Herd)

这是closest我遇到的这种模式,但是中间组:Dogs (Pack) 变成了 Group 0。

((.*?)(\(\w{1,}\)))((.*?)(\g<3>))*

【问题讨论】:

  • 关于 Q2,重复捕获组只保留最后匹配的出现,这是 SO 上的常见问题。 Q1 很容易回答,但需要时间来解释:recursion levels are atomic in PCRE
  • 另外,请参阅this thread,这甚至可能是欺骗的原因。
  • 谢谢你会看的。
  • 现在,如果您已经阅读了我在该主题上的回答,一切都清楚了吗?或者您需要澄清一下吗?
  • 关于第一部分,我已经浏览了链接和您的 SO 答案,但它仍然没有点击。我理解原子性,一旦找到匹配项,它就不会重新输入。我这里做错的其实和第一组的使用有关,是和组的定位有关,还是两者的结合?

标签: regex pcre regex-group regex-greedy regex-recursion


【解决方案1】:

请注意,PCRE 中的递归级别是原子的。一旦这些模式找到匹配项,就永远不会重试。

Recursion and Subroutine Calls May or May Not Be Atomic:

PerlRuby 如果递归后正则表达式的其余部分失败,则回溯到递归。他们根据需要尝试递归的所有排列,以允许正则表达式的其余部分匹配。 PCRE 将递归视为 atomic。 PCRE 在递归期间通常会回溯,但是一旦递归匹配,它就不会尝试任何进一步的递归排列,即使正则表达式的其余部分无法匹配。结果是 Perl 和 Ruby 可能会找到 PCRE 找不到的正则表达式匹配,或者 Perl 和 Ruby 可能会找到不同的正则表达式匹配。

你的第二个模式,在第一个递归级别,看起来像

((.*?)(\(\w{1,}\)))(((?>.*?))((?>\(\w{1,}\))))*
                     ^^^^^^^  ^^^^^^^^^^^^^^

demo。也就是说,\g&lt;2&gt;(?&gt;.*?),而不是 .*?。这意味着,在((.*?)(\(\w{1,}\))) 模式匹配Geese (Flock) 之后,正则表达式引擎尝试匹配(?&gt;.*?),发现它是一个不需要消耗任何字符的惰性模式,跳过它(并且永远不会回到此模式),并尝试与 (?&gt;\(\w{1,}\)) 匹配。由于) 之后没有(,因此正则表达式返回它所使用的内容。

关于第二个问题,这是一个常见的问题。使用 PCRE 正则表达式不可能获得任意数量的捕获,因为在重复捕获的情况下,只有最后一个捕获的值存储在组缓冲区中。结果数组中的子匹配数不能多于正则表达式模式内的捕获组数。详情请见Repeating a Capturing Group vs. Capturing a Repeated Group

【讨论】:

    猜你喜欢
    • 2014-12-10
    • 1970-01-01
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多