2013-06-01 14 views
13

In un codice sorgente ho trovato questo regex:Cosa corrisponde a questa espressione regolare: qr/(?!) /;

qr/(?!)/; 

Ho semplicemente non riesco a capire che cosa questo corrisponde.

Onestamente, assolutamente non capisco cosa significhi Asserzione di look-ahead negativo a larghezza zero. - quello che ho trovato nel perlre. :(

qualcuno può spiegare in un linguaggio umano, per favore? :)

risposta

14

È legale, ma non corrisponde a nulla.

Il costrutto (?!...) è un asserzione lookahead. In dettaglio, significa: "corrisponde a una posizione in cui la regex successiva (...) deve essere non corrispondente alla stringa di input".

Ma in questo caso, "regex che segue" è la regex vuota, che corrisponde a tutto.

Quindi, questa espressione regolare in sostanza dice "corrisponde a una posizione in cui ciò che segue non può essere corrisposto dalla regex vuota" ... E non può esserci una tale posizione, qualunque sia la stringa di input. Questo è un costrutto regex che fallisce sempre!

+0

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

+0

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

1

(?=), un vuoto positiva lookahead, corrisponde sempre. È un modo hacker per impostare il valore dell'ultima partita riuscita. (?!) è la sua inversa e non potrà mai corrispondere.

25

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:

  1. inizio corrispondente al pos 0.
  2. (.+?) partite a a pos 0
  3. (?{ print "$1\n" }) stampe a e corrisponde a zero caratteri
  4. (?!) non corrisponde. ⇒ Backtrack!
  5. (.+?) partite ab a pos 0
  6. (?{ print "$1\n" }) stampe ab e corrisponde a zero caratteri
  7. (?!) non corrisponde. ⇒ Backtrack!
  8. (.+?) partite abc a pos 0
  9. (?{ print "$1\n" }) stampe abc e corrisponde a zero caratteri
  10. (?!) non corrisponde. ⇒ Backtrack!
  11. (.+?) partite abcd a pos 0
  12. (?{ print "$1\n" }) stampe abcd e corrisponde a zero caratteri
  13. (?!) non corrisponde. ⇒ Backtrack!
  14. (.+?) non può corrispondere a nient'altro qui. ⇒ Backtrack!
  15. inizio corrispondente al pos 1.
  16. (.+?) partite b al pos 1
  17. (?{ print "$1\n" }) stampe b e corrisponde a zero caratteri
  18. (?!) non corrisponde. ⇒ Backtrack!
  19. ...
  20. (.+?) partite d a pos 3
  21. (?{ print "$1\n" }) stampe d e corrisponde a zero caratteri
  22. (?!) non corrisponde. ⇒ Backtrack!
  23. (.+?) non può corrispondere a nient'altro qui. ⇒ Backtrack!
  24. Inizia corrispondenza a pos.
  25. (.+?) non corrisponde. ⇒ Backtrack!
  26. Il modello non corrisponde.
+0

Ho bisogno di imparare molto di più per essere in grado di capire l'esempio. Capisco il '(. +?) = = abbina la stringa più breve possibile e aggiungila al gruppo di cattura, capisci il 'push ...', ma non hai idea del motivo per cui si tratta di ripetizioni - quindi perché dà il risultato sopra. Sono solo un principiante, ma grazie. ;) – novacik

+0

'(?!)' Non corrisponde, quindi il motore regex continua a cercare una corrispondenza avendo '. +?' Corrisponde più caratteri. 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 5 'a's, quindi' ab' non corrisponde, quindi torna indietro. La seconda volta, 'a *' corrisponde solo a 4 'a's, permettendo a' ab' di corrispondere. – ikegami

+0

... e pensavo di conoscere regex – kizzx2

Problemi correlati