【问题标题】:Nested greedy quantifier not matching嵌套贪心量词不匹配
【发布时间】:2014-07-17 02:23:17
【问题描述】:

我注意到 PCRE 正则表达式的一些奇怪行为,我无法解释。我希望代码:

preg_match('!^.+?(?:/programs/([^?#]+))?.*?$!',
    'http://example.com/programs/drive', $matches);

返回“驱动器”作为匹配1。非捕获组之后的[^?#]+?都是贪婪的,那么为什么[^?#]+不优先匹配drive?相反,测试显示开头的.+?h 匹配,而结尾的.*? 与URL 的其余部分匹配。

相比之下,代码:

preg_match('!^.+?(?:/programs/([^?#]+).*)?$!',
     'http://example.com/programs/drive', $matches);

按预期工作并返回 drive 作为匹配 1。

【问题讨论】:

  • @hwnd 我假设只匹配没有查询字符串或哈希的 URL,或者只匹配这些字符之前的组件。
  • @hwnd:不,它尽可能匹配零次或一次。这是贪婪的。

标签: php regex regex-greedy


【解决方案1】:

这是怎么回事。第一个.+? 应用于httph 之前的字符串开头。这是懒惰的,所以它立即放弃,(?:/programs/([^?#]+).*)?h 进行了测试。整个表达式是可选的,因此它也会在字符串开头不匹配后放弃。最后,应用模式末尾的.*?$,该表达式能够匹配字符串中的所有字符以成功匹配。

【讨论】:

  • +1。这是我看到regex101 debugger 后的想法,但我的正则表达式不够强大,无法确定确实如此。不过有一个疑问,为什么(?:/programs/([^?#]+).*)? 会失败?我假设这是因为正则表达式引擎在 h 位置时无法在其后找到 /programs/。或者是别的什么?如果我在表达式中将.+? 替换为http://example.com,它似乎可以工作。
  • 不错,山脊奔跑者! +1
  • @Amal Murali - (?:/programs/([^?#]+).*)? 表达式失败,因为它匹配的文本 必须 以正斜杠开头 - 在开头的 h 中不存在字符串。
猜你喜欢
  • 2013-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-01
  • 1970-01-01
相关资源
最近更新 更多