ProgrammationDéveloppeur Backend

Comment Perl gère-t-il les expressions régulières au format s/// (remplacements) : quelles sont les différences entre les modèles gourmands et paresseux, comment traiter correctement les chaînes multiligne et comment éviter des effets inattendus ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Perl est l'un des langages où les expressions régulières sont intégrées à un niveau profond. L'opérateur principal de remplacement est s///, qui permet de rechercher et de remplacer des fragments de chaînes selon un modèle. Cette construction cache de nombreux aspects subtils, en particulier lors de l'utilisation de modèles gourmands/paresseux, du traitement multiligne et des options de remplacement.

Contexte du sujet

L'opérateur s/// est présent dans Perl depuis les premières versions, et c'est Perl qui a posé les bases de la syntaxe des expressions régulières, plus tard empruntées par d'autres langages. La plupart des nuances de construction des modèles et des modificateurs (g, m, s, i, x, etc.) ont été introduites et développées précisément dans Perl.

Problème

Dans la pratique, de nombreux développeurs utilisent incorrectement les quantificateurs gourmands ou se mélangent dans les modificateurs (en particulier s et m), ce qui entraîne des résultats inattendus lors du remplacement dans des textes multiligne ou de grandes données. Des erreurs surviennent lors de l'attente d'une seule correspondance dans la chaîne, mais d'une autre, ou lors du remplacement uniquement des premières/dernières occurrences.

Solution

Il est important de choisir et de configurer correctement les modèles et de comprendre l'effet des modificateurs. Les modèles gourmands (par exemple, .*) capturent la plage maximale possible, tandis que les paresseux (par exemple, .*?) capturent la plage minimale requise.

Utilisation des modificateurs :

  • g — effectue le remplacement pour toutes les correspondances
  • s — active le mode de traitement des chaînes multiligne, où le point (.) capture les nouveaux caractères de ligne
  • m — change le comportement des marqueurs ^ et $

Exemple — remplacer les balises <tag> ... </tag> par un espace, un par un (paresseux) :

my $text = 'a <tag>1</tag> <tag>2</tag> b'; $text =~ s/<tag>.*?<\/tag>//g; print $text; # a b

Pour traiter des chaînes multiligne :

my $data = "Line 1 Line 2 <tag> DATA </tag> End"; $data =~ s/<tag>.*?<\/tag>//gs; print $data;

Caractéristiques clés :

  • Les modèles gourmands capturent la plage maximale, les modèles paresseux — la minimale
  • Le modificateur s permet au point (.) de capturer des retours à la ligne
  • Le modificateur g affecte le nombre de remplacements effectués

Questions piégeuses.

Que se passe-t-il si on ne met pas ? après le gourmand . lors du traitement de plusieurs balises ?*

Le quantificateur gourmand capturera la plage maximale possible, y compris les balises intermédiaires, ce qui entraînera la suppression inattendue de tout entre la première <tag> et la dernière </tag> :

my $txt = 'A <tag>1</tag> <tag>2</tag> B'; $txt =~ s/<tag>.*<\/tag>//g; print $txt; # A B

Ici, tout le morceau entre la première <tag> et la dernière </tag> a été remplacé.

Quelle est la différence entre le modificateur m et le modificateur s des expressions régulières Perl ?

s — le point (.) capture le caractère de nouvelle ligne ; m — change les ancres ^ et $ pour fonctionner à l'intérieur des lignes dans le texte multiligne. Leur utilisation est différente, mais on les confond souvent.

my $s = "abc def"; # /^def/ ne fonctionnera pas sans m print $s =~ /^def/m; # 1 (vrai)

Comment traiter toutes les occurrences d'un motif, si on applique s/// une seule fois ?

Sans le modificateur g, seule la première occurrence sera remplacée. Il faut ajouter g pour un remplacement global :

my $s = "foo bar foo"; $s =~ s/foo/baz/g; # remplacera les deux foo

Erreurs typiques et anti-modèles

  • Utilisation de modèles gourmands là où des paresseux sont nécessaires, entraînant la capture de données supplémentaires
  • Modificateur g manqué, ce qui fait que seule la première correspondance est remplacée
  • Ignorer les modificateurs s et m lors de la manipulation de données multiligne

Exemple de la vie

Cas négatif

Un développeur écrit un remplacement pour les balises HTML comme ceci :

$text =~ s/<tag>.*<\/tag>//g;

Résultat : tous les tags sont coupés avec le contenu entre eux — et non chacun séparément.

Avantages :

  • Code concis et clair
  • Réagit rapidement pour une seule occurrence

Inconvénients :

  • Résultat incorrect pour de nombreux fragments similaires
  • Violation de l'intégrité de la structure restante

Cas positif

Utiliser un modèle paresseux et des modificateurs corrects :

$text =~ s/<tag>.*?<\/tag>//gs;

Avantages :

  • Chaque bloc est remplacé correctement
  • Pas de captures superflues

Inconvénients :

  • Nécessite de connaître la syntaxe des modèles paresseux et des modificateurs