Su goloso vs non goloso
La ripetizione in regex per impostazione predefinita è avida : cercano di abbinare il maggior numero possibile di ripetizioni, e quando questo non funziona e devono tornare indietro, cercano di abbinare un numero di ripetizioni alla volta, fino a quando una corrispondenza dell'intero modello è trovato. Di conseguenza, quando alla fine accade una partita, una ripetizione avida corrisponderebbe a quante più ripetizioni possibili.
Il ?
quantificatore della ripetizione cambia questo comportamento in non avido , anche chiamato riluttante ( ad esempio Java ) (e talvolta "pigro"). Al contrario, questa ripetizione proverà prima ad abbinare il minor numero possibile di ripetizioni e quando questo non funziona e devono tornare indietro, iniziano ad abbinare un'altra ripetizione alla volta. Di conseguenza, quando finalmente si verifica una partita, una ripetizione riluttante corrisponderebbe al minor numero di ripetizioni possibile.
Riferimenti
Esempio 1: dalla A alla Z
Confrontiamo questi due schemi: A.*Z
e A.*?Z
.
Dato il seguente input:
eeeAiiZuuuuAoooZeeee
I modelli producono le seguenti corrispondenze:
Concentriamoci prima su cosa A.*Z
fa. Quando corrisponde al primo A
, il .*
, essendo avido, cerca innanzitutto di abbinarne il maggior numero .
possibile.
eeeAiiZuuuuAoooZeeee
\_______________/
A.* matched, Z can't match
Poiché Z
non corrisponde, il motore fa un passo indietro e .*
deve quindi corrispondere a uno in meno .
:
eeeAiiZuuuuAoooZeeee
\______________/
A.* matched, Z still can't match
Questo succede più volte, fino a quando finalmente arriviamo a questo:
eeeAiiZuuuuAoooZeeee
\__________/
A.* matched, Z can now match
Ora Z
può corrispondere, quindi lo schema generale corrisponde:
eeeAiiZuuuuAoooZeeee
\___________/
A.*Z matched
Al contrario, la riluttante ripetizione nelle A.*?Z
prime partite il meno .
possibile, e poi prendendo più .
se necessario. Questo spiega perché trova due corrispondenze nell'input.
Ecco una rappresentazione visiva di ciò che corrispondevano ai due modelli:
eeeAiiZuuuuAoooZeeee
\__/r \___/r r = reluctant
\____g____/ g = greedy
Esempio: un'alternativa
In molte applicazioni, le due corrispondenze nell'input precedente sono ciò che si desidera, quindi .*?
viene utilizzato un riluttante al posto dell'avido .*
per evitare il super-accoppiamento. Per questo particolare schema, tuttavia, esiste un'alternativa migliore, usando la classe di caratteri negata.
Il modello A[^Z]*Z
trova anche le stesse due corrispondenze del A.*?Z
modello per l'input sopra ( come visto su ideone.com ). [^Z]
è quella che viene definita una classe di caratteri negata : corrisponde a tutto tranne che a Z
.
La differenza principale tra i due modelli è nelle prestazioni: essendo più rigorosa, la classe di caratteri negata può corrispondere solo in un modo per un dato input. Non importa se usi questo modificatore avido o riluttante per questo schema. In effetti, in alcuni gusti, puoi fare ancora meglio e usare quello che viene chiamato quantificatore possessivo, che non fa affatto marcia indietro.
Riferimenti
Esempio 2: dalla A alla ZZ
Questo esempio dovrebbe essere illustrativo: mostra come i modelli di classe di personaggi avidi, riluttanti e negati si abbinano in modo diverso dato lo stesso input.
eeAiiZooAuuZZeeeZZfff
Queste sono le corrispondenze per l'input sopra:
Ecco una rappresentazione visiva di ciò che hanno abbinato:
___n
/ \ n = negated character class
eeAiiZooAuuZZeeeZZfff r = reluctant
\_________/r / g = greedy
\____________/g
argomenti correlati
Questi sono collegamenti a domande e risposte su StackOverflow che trattano alcuni argomenti che potrebbero essere di interesse.
Una ripetizione avida può superare un altro