Perl is een van de talen waarin reguliere expressies op een diepgaand niveau zijn geïntegreerd. De belangrijkste vervangingsoperator is s///, waarmee je fragmenten van strings op basis van een patroon kunt zoeken en vervangen. In deze constructie schuilen veel subtiele punten, vooral bij het werken met vraatzuchtige/lazy patronen, meerregelige verwerking en vervangingsopties.
De operator s/// bestaat in Perl sinds de vroege versies, en het was Perl die de fundamenten legde voor de syntaxis van reguliere expressies, die later door andere talen zijn overgenomen. De meeste nuances van patroonbouw en modificatoren (g, m, s, i, x, enz.) zijn ontstaan en zijn vooral in Perl ontwikkeld.
In de praktijk gebruiken veel ontwikkelaars vraatzuchtige kwantificators verkeerd of verwarren ze de modificatoren (vooral s en m), wat leidt tot onverwachte resultaten bij vervangingen in meerregelige teksten of grote gegevens. Fouten doen zich voor wanneer men één overeenkomst in een string verwacht, maar een andere krijgt, of bij het vervangen van alleen de eerste/laste voorkomens.
Het is belangrijk om patronen correct te kiezen en in te stellen en te begrijpen hoe modificatoren werken. Vraatzuchtige patronen (bijvoorbeeld .*) omvatten het maximaal mogelijke bereik, terwijl luie patronen (bijvoorbeeld .*?) het minimaal noodzakelijke omvatten.
Werken met modificatoren:
g — vervangt alle overeenkomstens — schakelt de modus voor het verwerken van meerregelige strings in, waarbij de punt (.) het nieuwe regelteken omvatm — verandert het gedrag van de markeringen ^ en $Voorbeeld — vervang <tag> ... </tag> tags met een spatie, maar één tag tegelijk (luie):
my $text = 'a <tag>1</tag> <tag>2</tag> b'; $text =~ s/<tag>.*?<\/tag>//g; print $text; # a b
Voor het verwerken van meerregelige strings:
my $data = "Regel 1 Regel 2 <tag> GEGEVENS </tag> Einde"; $data =~ s/<tag>.*?<\/tag>//gs; print $data;
Belangrijke kenmerken:
s laat de punt (.) nieuwe regels vangeng beïnvloedt het aantal uitgevoerde vervangingenWat gebeurt er als je geen ? na een vraatzuchtige . opgeeft bij het verwerken van meerdere tags?*
De vraatzuchtige kwantificator pakt het maximaal mogelijke bereik, inclusief tussenliggende tags, wat leidt tot onverwachte verwijdering van alles tussen de eerste <tag> en de laatste </tag>:
my $txt = 'A <tag>1</tag> <tag>2</tag> B'; $txt =~ s/<tag>.*<\/tag>//g; print $txt; # A B
Hier is het hele stuk tussen de eerste <tag> en de laatste </tag> vervangen.
Wat is het verschil tussen de modificator m en de modificator s in Perl reguliere expressies?
s — de punt (.) vangt het nieuwe regelteken; m — verandert de ankers ^ en $ zodat ze binnen regels in meerregelige tekst werken. Hun doelen zijn verschillend, maar ze worden vaak verward.
my $s = "abc def"; # /^def/ werkt niet zonder m print $s =~ /^def/m; # 1 (waar)
Hoe verwerk je alle voorkomens van een patroon als je s/// maar één keer toepast?
Zonder de modificator g wordt alleen het eerste voorkomen vervangen. Je moet g toevoegen voor globale vervangingen:
my $s = "foo bar foo"; $s =~ s/foo/baz/g; # vervangt beide foo
Een ontwikkelaar schrijft een vervanging voor HTML-tags als volgt:
$text =~ s/<tag>.*<\/tag>//g;
Het resultaat is dat alle tags samen met de inhoud ertussen worden verwijderd — en niet elk afzonderlijk.
Voordelen:
Nadelen:
Gebruik een luie patroon en de juiste modificatoren:
$text =~ s/<tag>.*?<\/tag>//gs;
Voordelen:
Nadelen: