2009-07-12 3 views
3

ich erwartet hatte diese "[b]" zu drucken, aber er druckt "[]":Warum scheint es, als ob der * in Perl regex nicht gierig ist?

$x = "abc"; 
$x =~ /(b*)/; 
print "[$1]"; 

Wenn der Stern mit einem Plus ersetzt wird, wirkt es wie ich erwarte. Sind nicht Plus und Stern gierig?

HINZUGEFÜGT: Danke an alle, die (in Sekunden, so schien es!) Darauf hingewiesen haben, dass "b *" mit der leeren Zeichenfolge übereinstimmt, deren erstes Auftreten vor dem Beginn der Zeichenfolge liegt. So ist Gier nicht das Problem überhaupt. Es stimmt mit der leeren Zeichenfolge überein, bevor es überhaupt zum ersten 'b' kommt.

Antwort

10

Es ist gierig, aber b* wird die leere Zeichenkette übereinstimmen. etwas * immer die leere Zeichenkette passen so,

"abc" 
    /\ 
    --- matches the empty string here. 

Wenn Sie $' drucken Sie werden sehen, es ist abc, was der Rest der Zeichenfolge nach dem Spiel ist. Gierigkeit bedeutet nur, dass Sie im Fall von "bbb" "bbb" und nicht "b" oder "bb" erhalten.

+2

Ich verstehe. So ist Gier nicht das Problem überhaupt. Es hat nie die Möglichkeit, gierig mit der Zeichenfolge von b übereinzustimmen, da sie mit der leeren Zeichenfolge am Anfang der Zeichenfolge übereinstimmt, bevor sie überhaupt mit den bs übereinstimmt. – dreeves

+0

Sie haben Recht, Sir. – chaos

3

Die Regex wird mit a(backtrack) übereinstimmen (was ein leerer Wert ist, seit die Regex zurückverfolgt wurde) und dort enden. Mit dem + Quantifizierer passt es nicht a oder c, so dass der Wert von $1b wird.

+1

Nicht ganz richtig. Es passt und endet bei "a", nicht "c". – chaos

+0

Ah, richtig, ich dachte daran als ein globales Spiel. Korrigiert. – Blixt

10

Das Muster stimmt überein und gibt das erste Mal zurück, b* ist wahr, d. H. Es wird eine nullbreite Übereinstimmung bei a durchgeführt. Um deutlicher zu veranschaulichen, was los ist, dies zu tun:

$x = "zabc"; 
$x =~ /(.b*)/; 
print "[$1]"; 
3

Die Regex paßt am frühesten Punkt in der Zeichenfolge, die es kann. Im Fall von 'abc' = ~/(b *)/liegt dieser Punkt genau am Anfang der Zeichenkette, wo er mit null b übereinstimmen kann. Wenn Sie versucht hatte, ‚bbc‘ passen, dann würden Sie gedruckt:

[bb]

0

Ein * am Ende eines Musters ist fast immer nicht das, was Sie wollen. Wir haben dies sogar als eine Trickfrage in Lernen Perl, nur um dieses Problem zu veranschaulichen.

1

Das Matching so früh wie möglich hat eine höhere Priorität als die Länge des Matchs (AFAIR dies ist der Fall von Perl Regex Matching-Engine, die ein NFA ist). Daher ist eine Null-Länge-Übereinstimmung am Anfang der Zeichenfolge wünschenswerter als eine längere Übereinstimmung später in der Zeichenfolge.

Für weitere Informationen suchen Sie nach "DFA vs NFA" in diesem article über Regex Matching Engines.