Warum Perl Regex '*? gierig bleiben?

8

Ich führe ein einfaches Programm:

%Vor%

OUT
/login/ /.htaccess/.htdf

Ich möchte, dass diese Regex nur mit /.htdf übereinstimmt.

Beispiel 2:

%Vor%

OUT
abcbc bcbc

Ich erwarte bc .

Warum ist *? immer noch gierig? (Ich möchte die minimale Übereinstimmung.)

    
Eugen Konkov 27.08.2015, 15:21
quelle

4 Antworten

8

Atome werden nacheinander abgeglichen, und jedes Atom nach dem ersten muss an der Position übereinstimmen, an der das vorhergehende Atom nicht übereinstimmte. (Dem ersten Atom wird implizit \A(?s:.)*? vorangestellt.) Das bedeutet, dass .* / .*? nicht zu der Entscheidung kommt, wo die Übereinstimmung beginnt. es kann nur entscheiden, wo es aufhört zu passen.

Beispiel 1

Es ist nicht gierig. \.ht bringt die Übereinstimmung auf Position 10 und auf Position 10 , die minimale .*? kann übereinstimmen und der Rest der Musterübereinstimmung ist weiterhin access/.htdf . In der Tat ist es das einzige, was .*? mit an Position 10 abgleichen kann und trotzdem den Rest des Patterns hat.

Ich denke, dass Sie den letzten Teil des Pfades entfernen möchten, wenn er mit .ht beginnt und die vorherige / an der richtigen Stelle belässt. Dafür können Sie eine der folgenden Möglichkeiten nutzen:

%Vor%

oder

%Vor%

Beispiel 2

Es ist nicht gierig. b bringt die Übereinstimmung zu Position 2, und zu Position 2 , das Minimum .*? kann übereinstimmen und der Rest der Musterübereinstimmung ist weiterhin cbc . Tatsächlich ist es das einzige, was .*? mit an Position 2 abgleichen kann und trotzdem den Rest des Pattern-Matches hat.

Sie suchen wahrscheinlich nach

%Vor%

oder

%Vor%     
ikegami 27.08.2015, 15:29
quelle
1

Sie können dafür ein negatives Lookahead verwenden:

%Vor%

RegEx Demo

(?!.*\.ht) ist ein negativer Lookahead, der sicherstellt, dass nach .ht kein .ht Vorkommen vorhanden ist und somit sichergestellt wird, dass nur der letzte .ht gefunden wird.

.*? wird nicht gierig sein, wenn auf der rechten Seite ein Muster vorhanden ist.

Code:

%Vor%     
anubhava 27.08.2015 15:26
quelle
1

Warum sollte es nicht? Die Gier ist in Vorwärtsrichtung, nicht rückwärts. Im nicht-gierigen Modus beginnt die Zustandsmaschine mit dem Abgleich und führt die Überprüfung bei jedem Schritt durch, statt nur alles zu kauen und dann zurückzuverfolgen, aber das garantiert Ihnen nicht die "minimale Übereinstimmung".

Vielleicht möchten Sie vermeiden, dass / übereinstimmt? Wie in s{/\.ht[^/]*$}{/} .

    
polettix 27.08.2015 15:32
quelle
0

Die Regex funktioniert so, wie Sie es gemacht haben.
Aber wenn Sie das Punkt-Metazeichen verwenden möchten, muss es gierig sein.

Das sollte funktionieren s!.*/\K\.ht.*$!! Es ist im Grunde genommen das Ende .ht...

Wenn Sie spezifisch sein möchten, benötigen Sie s!/\K\.htdf$!!

    
sln 27.08.2015 15:39
quelle

Tags und Links