Il modello di regex vuoto corrisponde a una stringa di lunghezza zero, vale a dire che corrisponde sempre. Si tratta di una progressione evidente:
'bbbbb' =~ /^(?:aaa|bbb)/ # Matches (Matches 3 "b"s, from pos 0 to 3)
'bbbbb' =~ /^(?:aaa|bb)/ # Matches (Matches 2 "b"s, from pos 0 to 2)
'bbbbb' =~ /^(?:aaa|b)/ # Matches (Matches 1 "b", from pos 0 to 1)
'bbbbb' =~ /^(?:aaa|)/ # Matches (Matches 0 "b"s, from pos 0 to 0)
Questo significa che (?=)
("? È questa posizione seguito da una stringa di lunghezza zero") corrisponde sempre e (?!)
("E 'questa la posizione non è seguito da una stringa di lunghezza zero?") non corrisponde mai. Infatti, (?!)
è ottimizzato per (*FAIL)
dall'introduzione di quest'ultimo in 5.10.
(?!)
(*FAIL)
è utile per forzare il backtracking quando il pattern ha effetti collaterali.
'abcd' =~ /(.+?)(?{ print "$1\n" })(?!)/;
uscita:
a
ab
abc
abcd
b
bc
bcd
c
cd
d
Spiegazione dell'esempio:
(?!)
non corrisponde, in modo che il motore regex continua a cercare di trovare una corrispondenza avendo .+?
partita sempre di più personaggi. Quando ciò non riesce, il motore regex tenta di corrispondere in una posizione di partenza successiva.
Questo è chiamato "backtracking". È come il motore regex può corrispondere a 'aaaab' =~ /a*ab/
. La prima volta, a*
corrisponde a tutti i 4 a
s, quindi lo ab
non corrisponde, quindi i backtracks del motore. La seconda volta, a*
corrisponde solo a 3 dei a
s, consentendo ab
e quindi l'intero modello da abbinare.
Il passo dal flusso di passo per l'esempio che ho dato in origine segue:
- inizio corrispondente al pos 0.
(.+?)
partite a
a pos 0
(?{ print "$1\n" })
stampe a
e corrisponde a zero caratteri
(?!)
non corrisponde. ⇒ Backtrack!
(.+?)
partite ab
a pos 0
(?{ print "$1\n" })
stampe ab
e corrisponde a zero caratteri
(?!)
non corrisponde. ⇒ Backtrack!
(.+?)
partite abc
a pos 0
(?{ print "$1\n" })
stampe abc
e corrisponde a zero caratteri
(?!)
non corrisponde. ⇒ Backtrack!
(.+?)
partite abcd
a pos 0
(?{ print "$1\n" })
stampe abcd
e corrisponde a zero caratteri
(?!)
non corrisponde. ⇒ Backtrack!
(.+?)
non può corrispondere a nient'altro qui. ⇒ Backtrack!
- inizio corrispondente al pos 1.
(.+?)
partite b
al pos 1
(?{ print "$1\n" })
stampe b
e corrisponde a zero caratteri
(?!)
non corrisponde. ⇒ Backtrack!
- ...
(.+?)
partite d
a pos 3
(?{ print "$1\n" })
stampe d
e corrisponde a zero caratteri
(?!)
non corrisponde. ⇒ Backtrack!
(.+?)
non può corrispondere a nient'altro qui. ⇒ Backtrack!
- Inizia corrispondenza a pos.
(.+?)
non corrisponde. ⇒ Backtrack!
- Il modello non corrisponde.
Non voglio mentire - quindi non posso dire: Ah, capisco perfettamente ora. Ma la tua spiegazione mi dà un po 'di luce nell'oscurità totale. Grazie. :) accetta. – novacik
Posso dare maggiori dettagli su richiesta;) In particolare, cosa significa _anchor_ in una regex. Se vuoi, posso dare una spiegazione completa e dettagliata del lavoro interiore delle ancore;) – fge