In Perl, i quantificatori nelle espressioni regolari — *, +, ?, {n,m} — sono affamati (greedy) per impostazione predefinita: catturano il numero massimo possibile di caratteri che corrispondono al pattern.
L'aggiunta di ? dopo il quantificatore lo trasforma in pigro (lazy o non-greedy): cattura il numero minimo possibile di caratteri affinché l'intera espressione regolare corrisponda.
my $str = 'foo <bar> baz <quux>'; $str =~ /<.*>/; # Catturerà '<bar> baz <quux>'
my $str = 'foo <bar> baz <quux>'; $str =~ /<.*?>/; # Catturerà '<bar>'
Un'espressione affamata può "mangiare" più di quanto ci si aspetti quando si fa il parsing di HTML e altre strutture annidate!
Qual è la differenza tra le seguenti due regex nel parsing della stringa
<a><b><c>:/<(.*)>/e/<(.*?)>/?
Risposta:
/<(.*)>/ (affamata) catturerà il blocco massimo — corrispondenza: <a><b><c>/<(.*?)>/ (pigra) — solo il primo gruppo: <a>Esempio:
my $s = '<a><b><c>'; $s =~ /<(.*)>/; # $1: 'a><b><c' $s =~ /<(.*?)>/; # $1: 'a'
Storia
In un'app per l'importazione di titoli di notizie, lo sviluppatore voleva fare il parsing del nome del tag nella stringa
<title>Notizia</title>, utilizzando/\<(.*)\>/. Alla fine, l'espressione regolare catturava l'intera stringa tra<e>ultima, e non l'elemento desiderato. L'errore è emerso quando sono apparsi tag annidati.
Storia
In un parser logico per estrarre stringhe citate, il pattern utilizzato
/"(.*)"/catturava inaspettatamente tutto tra la prima e l'ultima virgolette. Di conseguenza, il markup veniva spezzato in modo errato, fino a che non è stato sostituito con il pattern/"(.*?)"/.
Storia
In un parser CSV automatico con supporto per virgolette, il pattern "affamato" è stato scritto in modo errato, causando la fusione di più colonne in una sola. Il difetto nel parser fornito si è manifestato solo con dati di grandi dimensioni — la modifica pigra del pattern ha risolto il problema.