为什么这个带有反向引用的正则表达式在regex101中工作但在php中却没有?

时间:2017-01-01 12:15:28

标签: php regex

我有这样的正则表达式:

/(style=([\"']))([^\2]+)(\2)/

它在regex101中工作,但在php中它不匹配:

echo preg_replace("/(style=([\"']))([^\2]+)(\2)/", '$3', 'style="foo"'); 

这返回style="foo"而不是foo,为什么我的正则表达式在php中不起作用?

我也试过这个也不起作用:

/(style=([\"']))((?!\2).+)(\2)/

更新

这一次返回foo"为什么不foo

echo preg_replace("/(style=([\"']))([^\2]+)/", '$3', 'style="foo"');

2 个答案:

答案 0 :(得分:3)

PHP strings有自己的转义序列。双引号字符串中的\2变为字符U + 0002。要使用preg_replace将理解它的反向引用,您必须双重转义它,或者使用单引号字符串。

此外,后引用在字符类([^ ])内不起作用。您可以使用lazy quantifier*?)或negative look-ahead(?! ))代替。

除了字符U + 0002之外,

[^\2]+会匹配任何内容。由于输入(style="foo")字符串仅包含一对引号,因此尾随引号将强制[^\2]仅匹配三个字符。如果字符串包含更多HTML属性(style="foo" class="bar"),它将继续匹配,直到最后一个引用。

echo preg_replace("/(style=([\"']))(.*?)(\\2)/", '$3', 'style="foo"');
echo preg_replace('/(style=(["\']))(.*?)(\2)/', '$3', 'style="foo"');
echo preg_replace('/(style=(["\']))(((?!\2).)*)(\2)/', '$3', 'style="foo"');

答案 1 :(得分:1)

已经回答过,你不能在字符类中使用反向引用。提及比使用延迟点.*?更好的性能的另一个选项是" ... "'之间的TensorFlow document ... { {1}}使用pcre的negated class能够被同一组捕获。

'

您的样本只需要branch reset feature。另见few steps for completion (regex101)
如果使用其他正则表达式风格,可以使用php demo at eval.in