2013-11-03 11 views
7

questo:php undertsanding vs. avido nongreedy corrispondenza

preg_match('~foo(.*?)(bar)?~','foo bar',$m); 

mi dà questo:

Array 
(
    [0] => foo 
    [1] => 
) 

Sono un po 'confuso su questo. Ho capito che il gruppo 1 mi sta dando una stringa vuota, perché è una partita pigra. Ma non dovrei (bar)? essere goloso e quindi darmi il gruppo di cattura 2?

mi sembra ragionevole che quello che dovrei essere preliminari è

Array 
(
    [0] => foo 
    [1] => 
    [2] => bar 
) 

dove [1] è uno spazio. Eppure ... non sta succedendo. Perché?

+6

** Off-topic: ** Per favore cambia il tuo nome in 'mysqli_noobie ...'. Informazioni su [* prepared statements *] (http://j.mp/T9hLWi) e uso [PDO] (http://php.net/pdo) o [MySQLi] (http://php.net/mysqli) - [questo articolo] (http://j.mp/QEx8IB) ti aiuterà a decidere quale. Se scegli PDO, [ecco un buon tutorial] (http://j.mp/PoWehJ). – HamZa

+1

@HamZa Questo mi ha fatto ridere! – IMSoP

+1

Se funzionasse come ci si aspetterebbe che funzionasse, [0] sarebbe in realtà "foo bar". [0] è la partita completa. –

risposta

5

La risposta qui è sorprendentemente semplice. Il primo gruppo non corrisponde a nulla (al primo passaggio), nemmeno lo spazio. Il secondo gruppo cerca di abbinare lo spazio con "bar", che, naturalmente, fallisce. Se ci fosse qualcosa dietro a ciò che HAS doveva corrispondere, il motore ora tornerebbe indietro ed espanderebbe il primo gruppo di cattura per abbinarlo allo spazio. Ma è perfettamente a posto ora (il secondo gruppo in realtà può essere emtpy), quindi rimane così.

per produrre ciò che ci si aspetta, provate questo:

preg_replace('~foo(.*?)(bar)?_~', 'foo bar_', $m); 


In tua modifica, si è aggiunto un altro gruppo di cattura. (. *) ora è 2. Si abbina alla fine della stringa, come pensavate. Quindi hai ragione su quello, hai appena cambiato l'esempio ^^

+1

sì l'ho capito subito dopo averlo postato, e poi ho capito che non era l'ultimo a "bar", ma il '(. *)', grazie! – slinkhi

3

No, questo comportamento è corretto. Dal documentation on lazy matching:

se un quantificatore è seguito da un punto interrogativo, allora diventa pigro, e invece corrisponde al numero minimo di volte possibili

Dal (bar)? è facoltativo, (.*?) non lo fa è necessario abbinare qualsiasi cosa affinché l'espressione regolare abbia successo. Poiché lo spazio tra foo e bar non è stato catturato, l'espressione non può continuare e corrisponde a bar.

2

Entry '0' è sempre pieno gli abbinamenti che in questo caso è foo. Tuttavia, il primo gruppo corrispondente non corrisponde a nulla come * usato. Il secondo gruppo è facoltativo.

+0

Questo in realtà non risponde alla domanda. In realtà, se il primo gruppo non fosse pigro, il secondo catturerebbe la barra, anche se è ancora facoltativa. –

+0

@JohannesH. huh .. '(foo) (. *) (bar)?' mi dà davvero "bar" in '[2]' .. perché? – slinkhi

+1

Ecco perché tutti i gruppi di cattura sono golosi qui. Ciò significa che corrispondono il più possibile. (foo) corrisponde a foo (in [1]), ovviamente. (. *) corrisponde allo spazio e alla (barra) (in [2]). (bar)? corrisponde a niente (quindi no [3]) –