wiki:InsiaProgPerlRe

Sommaire

Programmation Perl - Expressions régulières

1. Généralités

Les expressions régulières représentent un langage à elles toute seule, embarqué dans des outils comme Java ou Perl, il s'agit d'un langage dans le langage ! Elles ont été conçues comme une généralisation du fameux "joker" (par exemple en SQL: LIKE 'a_virgin%'), afin de répondre à divers problèmes sur l'anlayse et le traitement des données textuelles:

  • trouver et compter des occurences de texte particulières
  • reconnaître ou valider une forme de texte particulière
  • remplacer des occurences de texte par une autre

Perl ayant été conçu originellement pour du "data mining", il intègre de manière très symbiotique le mécanismes des expressions régulières. A tel point que Perl a défini un standard officieux pour les expressions régulières les plus follesévoluées. En pratique, on distingue en général trois grandes familles d'expression régulières, qui ont toutes leur syntaxe propre même si elles partagent beaucoup d'éléments:

  • les expressions régulières POSIX ("Basique" ditesBRE, et "Etendues" dites Extended)
  • les expressions régulières Perl
  • les expressions régulières compatibles Perl (PCRE)

Aujourd'hui la plupart des outils Unix traditionnels (sed, grep, awk, etc) supportent la version POSIX Etendue. L'exemple le plus classique de l'utilisation des PCRE est constitué par les fonctions preg_* de PHP.

2. Forme générale

Matching

En perl, une expression régulière est en général délimitée par le caractère /. L'opérateur qui permet d'évaluer une expression régulière sur une chaîne de caractère est =~. Par exemple:

my $text = "Le chameau dans le desert";
print "Chameau en vue" if $text =~ /chameau/;

Cependant si l'on spécifie explicitement le préfixe m (matching, implicite par défaut), on est alors libre de changer le délimiteur, ce qui peut être très pratique pour l'échappement:

my $path = "/usr/bin/test";
print "un programme" if $path =~ m:/usr/bin/test:;

Par défaut, le résultat d'une opération de matching renvoie une valeur booléenne. Si on est à la recherche de plusieurs occurences et que l'on veut les compter, on utilise d'une part le suffixe g, et d'autre part on peut forcer l'évaluation en mode liste: Perl renvoie alors la liste des éléments de la chaîne qui matchent:

my $text = "un chasseur sachant chasser";
my @cha = $text =~ /cha/g;
print scalar(@cha)." occurences";

Enfin il est possible d'inverser le test:

my $text = "Le chameau dans le desert";
print "Pas de chameau à l'horizon" if $text !~ /chameau/;

Substitution

L'écriture est très similaire, mais cette fois l'opération consiste à éventuellement modifier la chaîne traitée:

my $text = "un chasseur sachant chasser";
$text =~ s/cha/cho/;  # text devient 'un chosseur sachant chasser'
$text =~ s/cha/cho/g; # text devient 'un chosseur sachont chosser'

On retrouve le même suffixe optionnel pour ne traiter que la première occurence (défaut) ou toutes les occurences (suffixe g).Une deuxième partie apparaît, qui spécifie le nouveau contenu lors des subtitutions: attention, cette deuxième partie n'est pas une expression regulière.

Le résultat de l'opération est toujours le nombre de substitutions, quel que soit le contexte (liste ou scalaire):

my $text = "un chasseur sachant chasser";
print ($text =~ s/cha/cho/g)." substitutions effectuéees";

Extraction

Hormis le contexte liste du mode matching, il existe un moyen général pour récupérer des motifs reconnus par une expression régulière, il suffit d'utiliser les parenthèses:

my @a = "Perl c'est bien"  =~ /(.*) c'est (.*)/;  # @a = ("Perl", "bien")
                                                  # $1 = "Perl"
                                                  # $2 = "bien"

La forme avec les variables $1, $2, etc. est la plus couramment utilisée.

3. Caractères spéciaux

Commençons par la liste des caractères spéciaux, c'est-à-dire qui on un sens particulier dans une expression regulière:

\ Echappement du cacactère suivant
, $ Début et fin de ligne
. Un caractère quelconque
| Alternative (ou logique)
() Groupement
[] Classes de caractère
* 0, 1 ou plusieurs occurences
+ 1 ou plusieurs occurences
? 0 ou 1 occurence
{} nombre variable d'occurences

Tous les autres caractères sont considérés et recherchés tels quels dans les chaînes à traiter. Cela signifie qu'en particulier, si l'on veut pouvoir identifier la chaîne 1+(2*3)=7, il faudra échapper les caractères spéciaux:

/1\+\(2\*3\)=7/

Avec Perl, il est possible d'échapper de manière complète une séquence simplement en délimitant son début et sa fin:

/\Q1+(2*3)\E/

4. Répétitions

Les motifs de recherche dans une expression de régulière peuvent être recherchés selon divers critères d'occurence:

(motif)* Recherche zero, une ou plusieurs occurences de motif
(motif)+ Recherche une ou plusieurs occurences de motif
(motif)? Recherche zero ou une occurence de motif
(motif){a} Recherche exactement a occurences de motif
(motif){a,b} Recherche entre a et b occurences de motif
(motif){a,} Recherche au moins a occurences de motif

Par défaut, l'opérateur de répétition ne s'adresse qu'au dernier caractère (ou classe de caractère, voir plus loin), on utilise donc les parenthèses (groupage) pour désigner un motif constitué de plusieurs caractères. Exemples:

/.*/ Recherche une occurence quelconque, y compris la chaîne vide
/erreurs?/ Recherche les occurence de "erreur" et "erreurs"
s/ +/ /g Remplace toutes les suites d'espace par un seul espace

5. Classes de caractère

Si l'on veut rechercher un motif ne correspondant pas à une simple chaîne, mais un agencement quelconques de caractères prédéfinis, on peut utiliser les classes de caractère:

[A-Z] Recherche n'importe quel caractère entre A et Z
[A-Za-z] Recherche n'importe quel caractère entre A et Z ou a et z
[^0-9] Recherche n'importe quel caractère qui n'est pas entre 0 et 9

Exemples:

[A-Z]{2}-[0-9]{4} Recherche un code de la forme XX-1234

Il existe des classes de caractères prédéfinies en Perl, elles permettent de gagner en concision. Chaque classe possède son complément (nom en majuscule décrivant une classe ne contenant pas les caractères désignés):

\w (\W) Caractère de mot, cad. alphanumérique et "_"
\s (\S) Espacement (espace, tabulation, retour chariot)
\d (\D) Numérique ([0-9])

6. Ancres

On peut également vérifier que le motif recherché est positionné à un endroit précis dans la chaîne de caractère, plus précisément au début où à la fin:

/^From (.*)/ Récupère dans $1 ce qui suit le "From " seulement si la ligne commence par "From "
s/!+$/./ Remplace une série de "!" en fin de ligne par un point
/^$/ Recherche les lignes vides
Last modified 10 years ago Last modified on Nov 5, 2010, 4:10:17 PM