2017-01-01 2 views
3

Ich habe Regex wie folgt aus:Warum funktioniert diese Regex mit Rückreferenzen in Regex101, aber nicht in PHP?

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

es in regex101 arbeiten, aber in php es nicht übereinstimmen:

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

diese Rückkehr style="foo" statt foo, warum meine regex arbeiten in nicht PHP?

Ich habe auch versucht dies, dass auch nicht funktionieren:

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

UPDATE:

diese Rückkehr foo" warum nicht foo:

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

Vielleicht nicht viel Hilfe. Aber ich habe Ihre Regex in .NET ausprobiert und es hat perfekt funktioniert. Nicht sicher, warum PHP Probleme damit hat. – silkfire

+1

[Eine Antwort] (http://stackoverflow.com/a/6051114/3536236) – Martin

+0

PHP kann HTML-Parsing durchführen, wenn dies Ihre Regex versucht: http://php.net/manual/en/domodocument .loadhtml.php – arcanine

Antwort

3

PHP strings haben ihre eigene Escape-Sequenzen. \2 in einer Zeichenfolge mit doppelten Anführungszeichen wird das Zeichen U + 0002. Um Rückverweise zu verwenden, so dass preg_replace es verstehen wird, müssen Sie es entweder doppelter Escape oder eine Zeichenfolge mit nur einem Anführungszeichen verwenden.

Auch Rückreferenzen funktioniert nicht innerhalb von Zeichenklassen ([^ ]). Sie könnten stattdessen eine lazy quantifier (*?) oder eine negative look-ahead ((?!)) verwenden.

[^\2]+ würde alles außer Zeichen U + 0002 übereinstimmen. Da die Eingabezeichenfolge (style="foo") nur ein Anführungszeichenpaar enthält, würde das nachfolgende Anführungszeichen [^\2] zwingen, nur drei Zeichen zu entsprechen. Wenn die Zeichenfolge mehr HTML-Attribute enthalten würde (style="foo" class="bar"), würde sie bis zum letzten Zitat übereinstimmen.

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"'); 
+0

backreference '[^ \\ 2] +' Arbeit für mich. – jcubic

+0

Es scheint nur zu funktionieren. Versuchen Sie es mit "style =" foo "class =" bar "'. –

1

Wird bereits beantwortet, dass Sie keine Backreferences innerhalb einer Zeichenklasse verwenden können. Um eine weitere Option für eine bessere Leistung als die Verwendung von Lazy Dot .*? zu nennen wäre ein negated class zwischen " ... " oder ' ... ' mit der Verwendung von pcre branch reset feature für die Aufnahme von der gleichen Gruppe.

$re = '/style=(?|"([^"]+)"|\'([^\']+)\')/'; 

Benötigt nur few steps for completion (regex101) mit Ihrer Probe. Siehe auch php demo at eval.in
Wenn Sie einen anderen Regex-Flavor verwenden, kann eine Problemumgehung zu use two groups and replace with $1$2 werden.

Verwandte Themen