I. Introduction aux expressions régulières▲
Théorie
- Théorie des automates et langages formels.
-
Grammaires de recherche de correspondances :
- DFA : Deterministic Finite Automaton ;
- NFA : Nondeterministic Finite Automaton.
- Principale différence : la gestion du retour en arrière (backtracking).
Historique
- UNIX : qed, ed, grep (BRE, puis ERE).
- POSIX regex (BRE, ERE).
- Perl 5, PCRE, Onigurama, (RE2 (DFA amélioré)).
- Perl 6.
Fonctionnement
- Correspondance de caractères.
-
Motif composé de :
- caractères normaux.
"Hello World" =~ /World/; # correspond
"Hello World" =~ /lo Wo/; # correspond aussi
"That hat is red" =~ /hat/; # le "hat" de "That" correspondFonctionnement
- Correspondance de caractères.
-
Motif composé de :
- caractères normaux ;
- métacaractères : {}[]()^$.|*+?\.
"2+2=4" =~ /2+2/; # ne correspond pas
"2+2=4" =~ /2\+2/; # correspond
"/usr/bin/perl" =~ /\/usr\/bin\/perl/;
"/usr/bin/perl" =~ m{/usr/bin/perl};Fonctionnement
- Correspondance de caractères.
-
Motif composé de :
- caractères normaux ;
- métacaractères : {}[]()^$.|*+?\ ;
- séquences d'échappement.
"1000\t2000" =~ /00\t20/; # correspond
"cat" =~ /\143\x61\x74/;# correspond aussi (même si c'est bizarre)Classes de caractères
- Ensemble de caractères possibles pour un emplacement de caractère.
- Notées par […].
/[bcr]at/; # cherche "bat", "cat", "rat"
/[yY][eE][sS]/; # cherche "yes", "Yes", YES", etc.
/yes/i; # pareil, mais plus lisibleClasses de caractères
- Ensemble de caractères possibles pour un emplacement de caractère.
- Notées par […].
- Intervalles de caractères.
/[0-9]/;# équivalent à /[0123456789]/
/[a-z]/;# équivalent à /[abcde...xyz]/
/[0-9a-fA-F]/; # chiffre hexadécimal
/item[0-9]/;# correspond à "item0", "item1"...Classes de caractères
- Ensemble de caractères possibles pour un emplacement de caractère.
- Notées par […].
- Intervalles de caractères.
- Négation de classe : [^...].
/[^0-9]/; # cherche un caractère qui n'est pas un chiffreClasses de caractères
-
Classes prédéfinies :
- . : tous caractères sauf \n ;
- \d : chiffre décimal ;
- \w : caractère de mot (alphanumérique plus _) ;
- \s : espace normale, tabulation, saut de ligne ;
- \h : espace horizontale ;
- \v : espace verticale ;
-
\R : saut de ligne.
-
Classes négatives prédéfinies :
- \D : ce qui n'est pas un chiffre décimal ;
- \W : ce qui n'est pas un caractère de mot ;
- \S : ce qui n'est pas une espace usuelle ;
- \H : ce qui n'est pas une espace horizontale ;
- \V : ce qui n'est pas une espace verticale.
Classes de caractères
- Exemples :
/\d\d:\d\d:\d\d/; # format d'heure hh:mm:ss
/[-+]\d/; # correspond à +2, -3, etc.
/end\./;# correspond à "end."
/end[.]/; # pareilAncres
- Pour ancrer la recherche dans certains points.
- ^ : en début de chaîne.
"beausoleil" =~ /^soleil/; # ne correspond pasAncres
- Pour ancrer la recherche dans certains points.
- ^ : en début de chaîne.
- $ : en fin de chaîne.
"beausoleil" =~ /beau$/;# ne correspond pas
"beausoleil" =~ /soleil$/; # correspond
"beausoleil\n" =~ /soleil$/;# correspond aussiAncres
- Pour ancrer la recherche dans certains points.
- ^ : en début de chaîne.
- $ : en fin de chaîne.
- \b : frontière de mot, intervient entre \w et \W.
"beausoleil" =~ /\bbeau/; # correspond
"beausoleil" =~ /\bbeau\b/; # ne correspond pas
"beausoleil" =~ /\bsoleil/; # ne correspond pasQuantifieurs
-
Répétition d'un sous-motif :
- * : zéro ou plusieurs fois ;
- + : une ou plusieurs fois ;
- ? : zéro ou une fois ;
- {n} : exactement n fois ;
- {n,} : au moins n fois ;
- {n,m} : entre n et m fois.
- Exemples :
"kraaack" =~ /kra+ck/; # correspond
"kraaack" =~ /kra{1,}ck/; # correspond aussi
"kraaack" =~ /kra{5,}ck/; # ne correspond pas
/\w+\d{2}/; # "item04", "machine42", "Kevin68", etc.
/\d+\.\d+\.\d+\.\d+/; # recherche simple d'une adresse IPv4
/<[-.\w]+\@[-.\w]+>/; # recherche simple d'une adresse mail
"aaaa" =~ /a+/; # correspond avec "aaaa"-
Quantifieurs non avides :
- *? : zéro ou plusieurs fois, au plus tôt ;
- +? : une ou plusieurs fois, au plus tôt ;
- ?? : zéro ou une fois, au plus tôt ;
- {n}? : exactement n fois, au plus tôt ;
- {n,}? : au moins n fois, au plus tôt ;
-
{n,m}? : entre n et m fois, au plus tôt.
- Exemples :
"aaaa" =~ /a+?/;# correspond avec "a"
^
"aaaabbbb" =~ /a+?b*?/; # correspond avec "a"
^
"aaaabbbb" =~ /a+?b+?/; # correspond avec "aaaab"
^^^^^-
Quantifieurs possessifs (nouveauté de Perl 5.10 et PCRE 7) :
- *+ : zéro ou plusieurs fois, et ne rend jamais ;
- ++ : une ou plusieurs fois, et ne rend jamais ;
- ?+ : zéro ou une fois, et ne rend jamais ;
- {n}+ : exactement n fois, et ne rend jamais ;
- {n,}+ : au moins n fois, et ne rend jamais ;
-
{n,m}+ : entre n et m fois, et ne rend jamais.
- Exemples :
"aaaa" =~ /a+a/; # /a+/ correspond avec "aaa"
^^^
"aaaa" =~ /a+?a/; # /a+?/ correspond avec "a"
^
"aaaa" =~ /a++a/; # /a++/ ne correspond pas- Résumé :
"Lorem ipsum dolor sit amet"
recherche avide : <<--| <<--| <<--| <<<<<--|
recherche non avide : |--->>> |---> |--->> |--->
recherche possessive : |---| |---| |---| |------|Groupes
- Pour grouper des sous-motifs : (…).
- Par défaut, groupes capturant.
- Référencés par \1, \2… dans le motif.
- Référencés par $1, $2… en dehors du motif.
-
Groupes non capturant : (?:…).
- Exemples :
/(\w+\d+ )+/; # "item04 machine42 Kevin68 "
/(?:\d+\.){3}\d+/; # recherche simple d'une adresse IPv4
/((?:\d+\.){3}\d+)/;# recherche simple d'une adresse IPv4
/(\w+) +\1/;# recherche d'un mot répétéAlternatives
- Disjonction de sous-motifs au sein d'un groupe.
- Exemple :
/^(add|del|list) +(addr|route|rule|table) .../
# "add addr ..."
# "del rule ..."
# "list route ..."Captures et alternatives
- Problème de la numérotation des captures.
/ ( a ) (?: x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x
# 1 2 3 4 5 6 7- Remise à zéro de branche : (?|..).
- Numérote les captures des branches d'une alternative comme s'il n'y en avait qu'une seule.
# before ------------branch-reset------------- after
/ ( a ) (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x
# 1 2 2 3 2 3 4Captures numérotées
- Nouvelle syntaxe de référencement : \g{N}.
- N positif : numéro de capture usuel.
- N négatif : référencement arrière relatif.
- \g{-1} == précédente capture.
- Exemple :
my $find_dup = qr/ (\w+) \s+ \g{-1} /x;Captures nommées
- (?<name>pattern) pour nommer une capture.
- \k<name>, \k{name} ou \g{name} pour s'y référer.
- Exemple :
my $find_dup = qr/ (?<dup_word>\w+) \s+ \k<dup_word> /x;Captures nommées
- Variables lexicales %+ et %-.
- $+{name} == \g{name}.
- $-{name} == référence vers un tableau de toutes les captures de ce nom.
- Tie::Hash::NamedCapture pour avoir des noms plus clairs.
Non abordés
- Modificateurs : /i, /m,/s, /x, /p, /r, /g, /c, /a, /d, /l, /u.
- Assertion keep, \K.
- Assertion \G.
- Assertions de longueur nulle, de recherche alentour positive ou négative : (?=..), (!..), (?<=..)>, (?<!..).
Non abordés
- Ensembles de classes (?[...]).
- Évaluation de code à la volée : (?{ code }), (??{ code }).
- Verbes de contrôle : (*PRUNE), (*SKIP), (*THEN), (*COMMIT), (*FAIL), (*ACCEPT).
- Unicode.
Motifs récursifs
- Possibles en Perl 5.8, mais de manière horrible.
- Syntaxe mise au propre dans PCRE.
- Principe : réinvocation d'un groupe capturant avec (?PARNO).
- PARNO == numéro de parenthèse (groupe capturant).
- Si précédé d'un signe, compris de manière relative.
Motifs récursifs
- (?2) => le 2e groupe déclaré.
- (?-1) => dernier groupe déclaré.
- (?+1) => prochain groupe qui sera déclaré.
- (?0) ou (?R) pour invoquer à nouveau le motif complet.
- (?&name) => invoque un groupe nommé.
Motifs récursifs
- Reconnaissance de parenthèses imbriquées :
$s = "( crack ( kapow ) ( klang ) ouch )";
$re = qr{ ( # groupe #1
\( # parenthèse ouvrante
(?:
(?> [^()]+ ) # groupe sans retour arrière
|
(?1) # groupe avec parenthèses
)*
\) # parenthèse fermante
)
}x;Motifs récursifs
-
(?(condition)yes-pattern|no-pattern) => construction conditionnelle, accepte :
- un numéro de groupe (1), (2)…
- un nom de groupe <name>,
- un bout de code Perl (?{ CODE }),
- (R) pour vérifier si évaluée au sein d'une récursion,
- avec numéro ((R1), (R2)..) ou nom ((R&name)) d'un groupe pour vérifier si évaluée pendant l'exécution du groupe.
Motifs récursifs
- Cas particulier : (DEFINE).
- Seule la partie yes-pattern est autorisée.
- N'est pas directement exécutée.
- Mais peut entrer dedans en récursion.
- Permet donc de définir des fonctions de regexps.
Motifs récursifs
my $log = "192.168.1.11 -> 192.168.1.12 connect tcp 80";
$log =~ m{
(?<src_addr>(?&ip_addr)) # adresse IP source
\s+ -> \s+
(?<dest_addr>(?&ip_addr)) # adresse IP destination
(?(DEFINE)
(?<ip_addr>...) # motif pour reconnaître une
) # addresse IP
}xEn ligne
- IRC : Freenode, #regex.
-
Bibliographie
-
Perl moderne par Sébastien Aperghis-Tramoni, Philippe Bruhat, Damien Krotkine, Jérôme Quelin.
- Mastering Regular Expressions, par Jeffrey E.F. Friedl.





