ProgrammazioneSviluppatore Fullstack

Spiega il principio del trattamento pigro e affamato dei quantificatori nelle espressioni regolari Perl. Come influisce sul parsing delle stringhe? Fai esempi di aspetti sottili e comportamenti non standard.

Supera i colloqui con l'assistente IA Hintsage

Risposta.

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.

Esempio di corrispondenza affamata:

my $str = 'foo <bar> baz <quux>'; $str =~ /<.*>/; # Catturerà '<bar> baz <quux>'

Esempio di corrispondenza pigra:

my $str = 'foo <bar> baz <quux>'; $str =~ /<.*?>/; # Catturerà '<bar>'

Caratteristica:

Un'espressione affamata può "mangiare" più di quanto ci si aspetti quando si fa il parsing di HTML e altre strutture annidate!


Domanda insidiosa.

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'

Esempi di errori reali dovuti a una mancanza di conoscenza delle sfumature dell'argomento.


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.