【问题标题】:Weird PHP Regex Preg_Match Bug?奇怪的 PHP 正则表达式 Preg_Match 错误?
【发布时间】:2021-04-08 10:40:37
【问题描述】:

我的 PHP 版本是PHP 7.2.24-0ubuntu0.18.04.7 (cli)。但是,我测试过的所有版本似乎都会出现此问题。

我在使用 preg_match 时遇到了一个非常奇怪的错误。有人知道解决办法吗?

这里的第一部分代码有效,第二部分无效。但是正则表达式本身是有效的。出于某种原因,something_happened 字导致它失败。

$one = ' (branch|leaf)';
echo "ONE:\n";
preg_match('/(?:\( ?)?((?:(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)+(?: ?\| ?(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)+)(?: ?\))?/', $one, $matches, PREG_OFFSET_CAPTURE);
print_r($matches); // this works

$two = 'something_happened (branch|leaf)';
echo "\nTWO:\n";
preg_match('/(?:\( ?)?((?:(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)+(?: ?\| ?(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)+)(?: ?\))?/', $two, $matches2, PREG_OFFSET_CAPTURE);
print_r($matches2); // this doesn't work

它似乎与something_happened 这个词有关。如果我改变这个词,它会起作用。

正则表达式匹配 2 个或多个由 | 分隔的类型名称,它们可能会或可能不会被 () 包围,并且每个类型名称前面可能有也可能没有任何数量的 [](或 @987654332 @ 或 [!some number]) 和 *

试试看吧!如果您知道如何解决,请告诉我!

【问题讨论】:

  • regex101 上尝试给我第二个示例的“灾难性回溯”错误。在3v4l 上运行问题中的代码与您的断言一致 - 第二种情况没有匹配项。 然而,在本地运行它会给我一个匹配。我很困惑。
  • 至于你说的情况“它似乎与something_happened这个词有某种关系。如果我改变这个词它会起作用。” - 似乎长度会影响它(见fiddle),考虑到 Regex101 站点上的正则表达式引擎提到的回溯,这是有道理的。
  • 请检查this fix,它是否按预期工作?
  • @WiktorStribiżew 是的,看起来它正确匹配!你改变了什么?想把它作为答案吗?

标签: php regex preg-match


【解决方案1】:

问题在于(?:(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)+ 组:+ 量词量化了具有许多后续可选模式的组,这会创建太多选项来匹配后续模式之前的字符串。

在 PHP 中,您可以使用任一方法解决此问题

  1. 占有量词:
'/(?:\(\ ?)?((?:(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)++(?:\ ?\|\ ?(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)+)(?:\ ?\))?/'

请注意提到的组末尾的++。 2.原子团:

'/(?:\(\ ?)?((?>(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)+(?:\ ?\|\ ?(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)+)(?:\ ?\))?/'

this regex demo。注意(?>...) 语法。

另外,请注意正则表达式是如何格式化here,使用x(扩展)标志将正则表达式分成几行非常方便,格式化它,以便更容易追踪问题。需要转义所有文字空格和# 字符,但在调试这样的长模式时会带来一点不便。

【讨论】:

  • 太棒了!问题:我可以在以前使用?: 的所有地方都使用?> 吗?我为什么要让它回溯?
  • @Alasdair 这取决于您是否要在匹配失败时重新匹配组中的模式。你不能盲目地使用所有格量词或原子组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-14
  • 2013-07-13
  • 1970-01-01
相关资源
最近更新 更多