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.*Ze A.*?Z.
Dato il seguente input:
eeeAiiZuuuuAoooZeeee
I modelli producono le seguenti corrispondenze:
Concentriamoci prima su cosa A.*Zfa. Quando corrisponde al primo A, il .*, essendo avido, cerca innanzitutto di abbinarne il maggior numero .possibile.
eeeAiiZuuuuAoooZeeee
\_______________/
A.* matched, Z can't match
Poiché Znon 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 Zpuò corrispondere, quindi lo schema generale corrisponde:
eeeAiiZuuuuAoooZeeee
\___________/
A.*Z matched
Al contrario, la riluttante ripetizione nelle A.*?Zprime 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]*Ztrova anche le stesse due corrispondenze del A.*?Zmodello 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