Archiv verlassen und diese Seite im Standarddesign anzeigen : [PHP] Negative Lookbehind-Assertion -> Verständnisproblem
Servus,
ich steh mal wieder vor einen kleinen Problem was mir nicht so ganz in den Kopf will.
Ich experimentiere gerade ein wenig mit Negative Lookbehind-Assertions rum. Die Beispiele funktionieren alle wunderbar aber ein Pattern was - nach meiner Logik nach funktionieren sollte - funktioniert nicht. Wahrscheinlich übersehe ich da einfach nur wieder irgendetwas aber nur was?
Der Quelltext ist hoffentlich selbst erklärend ;)
<?php
// funktioniert
$text = "foobar";
preg_match("/^(?<!foo)bar$/", $text, $match);
echo "1: <pre>" . print_r($match, true) . "</pre>";
// funtkioniert nicht
$text = "abcdefg";
preg_match("/^(?<!abc)(.*)$/", $text, $match);
echo "2: <pre>" . print_r($match, true) . "</pre>";
?>
ich denke, es liegt daran, dass .* greedy ist und auf den kompletten string matcht. "bar" hingegen beim oberen beispiel matcht auch nur auf "bar" in "foobar"
teste mal .... oder .*?
nein das macht keinen Unterschied ... dadurch das ich $ verwendet habe matcht der mir automatisch bis ans Ende der Zeile
ganz lustigerweise aber funktioniert das Pattern wieder wenn ich folgendes Pattern verwende:
^(?<!abc)defg$
Also meine Frage deshalb: Warum kann ich bei dieser Assertion keine Platzhalter verwenden?
Jan Krüger
18.01.2006, 23:50
^(?<!foo)bar$ trifft genau dann zu, wenn direkt vor dem Anfang einer beliebigen Zeile (^) nicht "foo" steht (und das ist nie der Fall, denn vor dem Anfang der Zeile fängt der String entweder gerade an, oder es ist mindestens ein Zeilenumbruch davor), und danach bar. Der Ausdruck trifft folglich auf jeden String zu, der in einer Zeile genau "bar" stehen hat.
Hilft dir das beim Verstehen?
Nein, denn du hast mir genau das erzählt was ich verstanden habe ;)
Den 2. Regex (eine Eigenkreation) da konnte ich nicht verstehen warum der gematcht hat aber mittlerweile bin ich zu den Schluss gekommen das es sehr wahrscheinlich daran liegt das (.*) nicht eindeutig genug ist damit der RegEx vor (.*) irgendwas findet was er nicht finden darf ;)
Jan Krüger
19.01.2006, 10:39
Hm? Bei mir matcht der zweite Pattern.
Richtig er matcht aber auf abcdefg sollte /^(?<!abc)(.*)$/ eigentlich nicht matchen - (?<!abc)(.*) sagt ja aus "matche alles nach der Klammer wenn zuvor kein 'abc' auftaucht" aber genau das ist der Fall - tausche einfach mal gegen /^(?<!abc)defg$/ aus dann siehst was mich meinte ich wollte den hinteren Teil Variable halten aber (.*) ist anscheinend zu allgemein so das der Pattern funktioniert.
Jan Krüger
19.01.2006, 21:22
(?<!abc)(.*) sagt ja aus "matche alles nach der Klammer wenn zuvor kein 'abc' auftaucht"
Das ist richtig, aber davor steht ja ein ^. Das bedeutet: Matche nur am Zeilenanfang. Das defg steht aber nicht am Zeilenanfang, also muss das .* wohl oder übel auf die ganze Zeile matchen (nicht, dass es sich dran stört... .* ist verdammt gierig ;)).
tausche einfach mal gegen /^(?<!abc)defg$/ aus dann siehst was mich meinte
Das sollte auf "abcdefg" gar nicht matchen, denn in diesem String fängt schließlich keine Zeile mit defg an.
Das sollte auf "abcdefg" gar nicht matchen, denn in diesem String fängt schließlich keine Zeile mit defg an.
Es sollte doch auch schon deshalb nicht matchen weil abc davor steht?
Jan Krüger
21.01.2006, 00:10
Wieso, die Assertion bezieht sich doch auf ^ (das ist intern auch eine Assertion), also auf das, was vor dem Anfang des Strings bzw. vor einem Zeilenumbruch steht. In deinem Beispiel gibt es keine Zeilenumbrüche und vor dem Anfang eines Strings kann kein Text stehen, also auch kein "abc". Folglich wird die Assertion erfüllt.
Irgendwie ist mir das nicht so ganz verständlich muss ich wohl noch mal die 2 Bücher wälzen die ich hier habe obwohl die Assertions da leider nicht sogut drinn erklärt stehen. Ich dachte bisher immer die Bücher von O'Reily sind ganz gut aber indem findet man echt nichts über Assertions :(
vBulletin® v3.8.6, Copyright ©2000-2012, Jelsoft Enterprises Ltd.