2010-03-24 15 views
7

mit Ruby regexp erhalte ich folgende Ergebnisse:Ruby Regexp: + vs *. besonderes Verhalten?

>> 'foobar'[/o+/] 
=> "oo" 
>> 'foobar'[/o*/] 
=> "" 

Aber:

>> 'foobar'[/fo+/] 
=> "foo" 
>> 'foobar'[/fo*/] 
=> "foo" 

Die Dokumentation sagt:
*: null oder mehr Wiederholungen der vorhergehenden
+: eine oder mehrere Wiederholungen der vorhergehenden

Also ich erwarte, dass 'Foobar' [/ o * /] das gleiche Ergebnis wie 'Foobar' [/ o + /]

zurückgibt

Hat für diese eine Erklärung jemand haben

Antwort

14

'foobar'[/o*/] wird die Null o s passend, die vor dem f erscheinen, an der Position 0
'foobar'[/o+/] kann dort nicht überein, da es mindestens 1 o, so es sein muss stattdessen passt alle o s von Position 1

Insbesondere die Spiele Sie sehen, sind

'foobar'[/o*/]=>'<>foobar'
'foobar'[/o+/]=>'f<oo>bar'

3

Dies ist ein weit verbreitetes Missverständnis, wie regexp funktioniert.

Obwohl das * gierig ist und nicht am Anfang der Zeichenfolge verankert ist, beginnt die Regexp-Engine immer vom Anfang der Zeichenfolge aus zu suchen. Im Falle von "/ o + /" stimmt es nicht an der Position 0 überein (zB "f"), aber da das + eins oder mehr bedeutet, muss es weiterpassen (das hat nichts mit der Gier zu tun), bis a Übereinstimmung gefunden oder alle Positionen ausgewertet

Aber mit dem Fall von "/ o * /", was, wie Sie wissen, 0 oder mehr bedeutet, wenn es nicht auf Position 0 übereinstimmt, wird die Regexp-Engine an diesem Punkt anmutig stoppen (wie es sollte, weil o * einfach bedeutet, dass das o optional ist). Es gibt auch Leistungsgründe, denn "o" ist optional, warum sollte man mehr Zeit darauf verwenden?