Perl è uno dei linguaggi in cui le espressioni regolari sono integrate a un livello profondo. L'operatore principale di sostituzione è s///, che consente di cercare e sostituire frammenti di stringhe in base a un pattern. In questa costruzione ci sono molti aspetti sottili, specialmente quando si lavora con pattern greedy/lazy, elaborazione multilinea e opzioni di sostituzione.
L'operatore s/// è presente in Perl fin dalle prime versioni, e proprio Perl ha gettato le basi della sintassi delle espressioni regolari, successivamente adottate da altri linguaggi. La maggior parte delle sfumature nella costruzione dei pattern e dei modificatori (g, m, s, i, x, ecc.) sono state sviluppate proprio in Perl.
Nella pratica, molti sviluppatori utilizzano in modo errato i quantificatori greedy o confondono i modificatori (in particolare s e m), il che porta a risultati imprevisti durante la sostituzione in testi multilinea o in grandi dati. Si verificano errori quando ci si aspetta una corrispondenza in una stringa, ma si ottiene un'altra, oppure quando si sostituiscono solo le prime/ultime occorrenze.
È importante scegliere e configurare correttamente i pattern e comprendere il funzionamento dei modificatori. I pattern greedy (ad esempio, .*) catturano l'intervallo massimo possibile, mentre quelli lazy (ad esempio, .*?) catturano il minimo necessario.
Funzionamento dei modificatori:
g — esegue la sostituzione per tutte le corrispondenzes — abilita la gestione delle stringhe multilinea, in cui il punto (.) cattura il carattere di fine rigam — modifica il comportamento degli ancoraggi ^ e $Esempio — sostituire i tag <tag> ... </tag> con uno spazio solo per un tag alla volta (lazy):
my $text = 'a <tag>1</tag> <tag>2</tag> b'; $text =~ s/<tag>.*?<\/tag>//g; print $text; # a b
Per elaborare stringhe multilinea:
my $data = "Line 1 Line 2 <tag> DATA </tag> End"; $data =~ s/<tag>.*?<\/tag>//gs; print $data;
Caratteristiche chiave:
s consente al punto (.) di catturare i ritorni a capog influisce sul numero di sostituzioni effettuateCosa succede se non si specifica ? dopo greedy . durante l'elaborazione di più tag?*
Il quantificatore greedy catturerà l'intervallo massimo possibile, inclusi i tag intermedi, portando alla rimozione inaspettata di tutto tra il primo <tag> e l'ultimo </tag>:
my $txt = 'A <tag>1</tag> <tag>2</tag> B'; $txt =~ s/<tag>.*<\/tag>//g; print $txt; # A B
Qui è stato sostituito l'intero pezzo tra il primo <tag> e l'ultimo </tag>.
Qual è la differenza tra il modificatore m e il modificatore s nelle espressioni regolari in Perl?
s — il punto (.) cattura il carattere di nuova linea; m — modifica gli ancoraggi ^ e $ per lavorare all'interno delle righe in un testo multilinea. I loro scopi sono diversi, ma spesso vengono confusi.
my $s = "abc def"; # /^def/ non funzionerà senza m print $s =~ /^def/m; # 1 (true)
Come gestire tutte le occorrenze di un pattern se si applica s/// solo una volta?
Senza il modificatore g verrà sostituita solo la prima occorrenza. È necessario aggiungere g per una sostituzione globale:
my $s = "foo bar foo"; $s =~ s/foo/baz/g; # sostituirà entrambi foo
Lo sviluppatore scrive una sostituzione per i tag HTML in questo modo:
$text =~ s/<tag>.*<\/tag>//g;
Di conseguenza, dal testo vengono rimossi tutti i tag insieme al contenuto tra di essi — e non ciascuno separatamente.
Pro:
Contro:
Utilizzare un pattern lazy e i modificatori corretti:
$text =~ s/<tag>.*?<\/tag>//gs;
Pro:
Contro: