我在 PHP 中使用可能为空的反向引用的正则表达式遇到问题。我希望它会按照http://www.regular-expressions.info/brackets.html中的说明工作:
如果在特定的匹配尝试中未使用反向引用(例如在第一个示例中,问号使第一个反向引用可选),则它只是空的。在正则表达式中使用空的反向引用非常好。它只会被虚无所取代。
然而,PHP 似乎有点不同......来自http://php.net/manual/en/regexp.reference.back-references.php:
如果子模式实际上没有在特定匹配中使用,那么对它的任何反向引用总是会失败。
作为一个简化的例子,我想用这个正则表达式匹配以下两件事:
- {某事} ... {/某事}
- {something:else} ... {/something:else}
其中“某事”是提前知道的,而“其他”可以是任何东西(或什么都没有)。
所以我尝试了以下正则表达式(为简单起见,硬编码“else”):
preg_match("/\{(something(:else)?)\}(.*?)\{\/something\\2\}/is", $data, $matches)
不幸的是 if (:else)? 不匹配,\2 反向引用失败。如果我将 \2 设为可选 (\2?),那么我可能会匹配 {something} ... {something:else},这并不好。
我是否遇到了正则表达式的限制(臭名昭著的“你需要一个解析器,而不是一个正则表达式”)还是可以修复?
测试程序:
<?php
$data = "{something} ... {/something}
{something:else} ... {/something:else}
{something:else} ... {/something}";
// won't match {something} ... {/something}
preg_match_all("/\{(something(:else)?)\}(.*?)\{\/something\\2\}/is", $data, $matches);
print_r($matches);
// change \\2 to \\2? and it matches too much
preg_match_all("/\{(something(:else)?)\}(.*?)\{\/something\\2?\}/is", $data, $matches);
print_r($matches);
?>