Trouvé sur : publish.ez.no

Les expressions régulières/rationnelles expliquées



Cet article est une introduction au monde des expressions régulières. Je commencerai par expliquer ce que sont les expressions régulières et vous présenter leur syntaxe, puis quelques exemples de complexité variable, et enfin une liste des outils qui utilisent les expressions régulières.

[PUPPY/TOUTOU a un outil d'évaluation et d'étude des expressions régulières dans le menu Utilitaires]

Concept

Une expression régulière est un modèle/motif de texte consistant en une combinaison de caractères alphanumériques et de caractères spéciaux appelés méta-caractères. Un parent proche est en fait le joker qui est souvent utilisé dans la gestion de fichier. Le modèle est utilisé pour faire correspondre des chaînes de caractères. Une correspondance peut être trouvée ou non, pourtant quand une correspondance au motif est trouvée, elle peut ne pas être complète, c'est expliqué plus loin dans l'article.

Vous comprendrez que les expressions régulières sont utilisées de trois manières différentes : correspondance à un texte simple, recherche et remplacement, et fragmentation. Cette dernière est essentiellement identique à une correspondance inverse, c'est-à-dire tout ce qui ne correspond pas à l'expression régulière.

Les expressions régulières sont souvent simplement appelées regexps ou RE, mais ici j'y ferai référence en utilisant le nom complet.

En raison de la polyvalence de l'expression régulière elle est largement utilisée dans le traitement de texte et l'analyse syntaxique. Les utilisateurs UNIX sont probablement familiers avec elle au travers de l'utilisation des programmes, grep, sed, awk et ed. Des éditeurs de textes comme (X)Emacs et vi l'utilisent aussi fréquemment. L'utilisation la plus connue des expressions régulières est probablement celle du langage de programmation Perl, vous remarquerez que Perl supporte l'implémentation la plus avancée à ce jour, des expression régulières.

Utilisation

Maintenant vous vous demandez probablement pourquoi vous devriez vous donner la peine d'apprendre les expressions régulières. Eh bien, si vous êtes un utilisateur normal d'ordinateur, le bénéfice à en tirer sera peu important, mais si vous êtes développeur ou administrateur système, vous constaterez que la connaissance des expressions régulières améliorera beaucoup votre vie (professionnelle).

Les développeurs peuvent les utiliser pour faire l'analyse syntaxique de fichiers texte, arranger du code ou d'autres merveilles. Les administrateurs système peuvent s'en servir pour rechercher dans des fichiers de journalisation, automatiser des tâches ennuyeuses ou parcourir le trafic réseau à la recherche d'activité non autorisée.

J'irai même jusqu'à dire que c'est réellement un crime pour un administrateur système de n'avoir aucune connaissance sur les expressions régulières.

Quantificateurs

Avant de commencer l'explication de la syntaxe, vous pouvez sauter à la dernière page pour connaître quels programmes utiliser pour évaluer les exemples de cet article.

Le contenu d'une expression est, comme expliqué plus haut, une combinaison de caractères alphanumériques et de méta-caractères. Un caractère alphanumérique est soit une lettre de l'alphabet

abc
soit un chiffre

123
En réalité dans le monde des expressions régulières, chaque caractère qui n'est pas un méta-caractère correspondra à lui-même (souvent appelés caractères littéraux), cependant la plupart du temps vous êtes surtout concernés par les caractères alphanumériques. Un caractère très spécial est l'antislash \, qui transforme chaque méta-caractère en caractère littéral et les caractères alphanumériques en une sorte de méta-caractère ou séquence. Les méta-caractères sont :

\ | ( ) [ ] ^ $ * + ? . < >
Cela étant dit les caractères normaux ne semblent pas très intéressants, passons directement à nos tous premiers méta-caractères.

D'abord, le signe de ponctuation, ou point, ., nécessite des explications car il prête souvent à confusion. Ce caractère ne correspondra pas, comme on pourrait le penser, à la ponctuation dans une ligne. C'est au lieu de cela un méta-caractère spécial qui correspond à n'importe quel caractère. Son utilisation afin de trouver la fin d'une phrase ou la décimale dans un nombre flottant vous renverra d'étranges résultats. Comme expliqué ci-dessus, vous avez besoin de l'antislash pour obtenir sa signification littérale. Prenez par exemple cette expression

1.23
correspondra au nombre 1.23 dans un texte comme vous pourriez l'avoir deviné, mais il correspondra aussi aux lignes suivantes

1x23
1 23
1-23
pour que l'expression retourne uniquement le nombre flottant, changeons-la en

1\.23
Ne l'oubliez pas, c'est très important. Maintenant cela étant dit, nous pouvons poursuivre la visite.

Deux méta-caractères sont récurrents

* et +
Ils sont appelés des quantificateurs et indiquent de chercher plusieurs répétitions d'un caractère, le quantificateur succède toujours au caractère au plus près. Le caractère * correspond à une succession de zéro caractère ou plus, le caractère + est semblable, mais correspond à une succession de un caractère ou plus.

Et si vous avez décidé de trouver les mots qui possède le caractère c vous pourriez être tentés d'écrire :

c*
Ce qui pourrait vous étonner c'est que vous vous trouverez devant une énorme quantité de correspondances, même les mots sans c correspondront. Vous vous demander pourquoi, et bien la réponse est simple. Rappelez-vous que le caractère * correspond à une répétition de zéro caractère ou plus. Eh bien c'est exactement ce que vous avez fait, aucun caractère correspondant.
Vous remarquerez que dans les expressions régulières vous avez la possibilité de faire correspondre ce qui est appelé la chaîne vide, qui est simplement une chaîne de caractères de taille nulle. Cette chaîne vide peut en réalité être trouvée dans tous les textes, par exemple le mot :

go
contient trois chaînes vides. Elles se trouvent à droite avant le g, entre le g et le o et après le o. Et une chaîne vide contient exactement une chaîne vide. D'abord cela pourrait sembler vraiment idiot à faire mais vous apprendrez plus tard comment c'est utilisé dans des expressions plus complexes.

Sachant cela, nous pouvons changer notre expression :

c+
et voilà, nous n'obtenons que les mots contenant c.

Le prochain méta-caractère que vous apprendrez est :

?
Cela indique simplement une correspondance facultative du caractère (zéro ou un). Par exemple l'expression :

cows?
renverra chacune de ces lignes :

cow
cows

Ces trois méta-caractères sont simplement des formes spéciales d'un quantificateur plus général

{n,m}
le n et le m sont respectivement la taille minimale et maximale pour le quantificateur. Par exemple :

{1,5}
signifie une répétition de un ou jusqu'à cinq caractères. Vous pouvez aussi éviter le m pour prendre en compte une correspondance infinie :

{1,}
qui correspond à un caractère ou plusieurs. C'est exactement ce que le méta-caractère + fait. Si maintenant vous voyez le rapport, * est identique à {0,}, + est identique à {1,} et ? est identique à {0,1}.
La dernière chose que vous pouvez faire avec le quantificateur est d'éviter aussi la virgule

{5}
qui signifie correspondre à 5 caractères, ni plus ni moins.

Assertions

Le type suivant de méta-caractères est l'assertion, celle-ci correspondra si une affirmation donnée est vraie. La première paire d'assertions est

^ et $
qui correspondent au début et à la fin de la ligne. Notez que certaines mises en oeuvres d'expressions régulières vous permettent de changer leurs comportements pour qu'elles correspondent au lieu de cela, au début et à la fin du texte. Ces assertions correspondent toujours à une chaîne de longueur nulle, ou autrement dit elles correspondent à une position. Par exemple si vous avez écrit cette expression :

^The
correspondrait à chaque ligne qui commence par le mot The.

Les prochains caractères d'assertions correspondent au début et à la fin d'un mot, ce sont :

< et >
ils s'avèrent pratique quand vous voulez une correspondance à un mot précisément, par exemple :

cow
renverrait chacun des mots suivants

cow
coward
cowage
cowboy
cowl
un petit changement à l'expression :

<cow>
et vous auriez seulement une correspondance au mot cow dans le texte.

Une dernière chose doit être dite, tous les caractères littéraux sont en fait des assertions eux-mêmes, la différence est que les littéraux ont une taille. Ainsi dans un souci de clarté, nous utilisons le mot assertion seulement pour ceux qui sont de taille nulle.

Groupes et alternances

Une chose que vous pourriez avoir remarqué quand nous avons expliqué les quantificateurs est qu'ils ont fonctionné seulement sur le caractère à leur gauche. Puisque cela limite beaucoup nos expressions, j'expliquerai d'autres utilisations des quantificateurs. Les quantificateurs peuvent aussi être utilisés sur des méta-caractères, les utiliser sur des assertions est idiot puisqu'elles sont de taille nulle et la correspondance à une, deux, trois ou plus d'entre elles est inutile. Cependant le groupement et la séquence de méta-caractères sont parfaits pour être quantifiés. Commençons d'abord par le groupement.

Vous pouvez former des groupes, ou des sous-expressions comme ils sont fréquemment appelés, en utilisant des parenthèses :

( et )
( commence la sous-expression et ) la termine. Il est aussi possible d'inclure une ou plusieurs sous-expressions à l'intérieur de sous-expressions. La sous-expression correspondra si le contenu correspond. Ainsi en mixant ceci avec des quantificateurs et des assertions vous pouvez faire :

( ?ho)+
qui correspond à toutes les lignes suivantes

ho
ho ho
ho ho ho
hohoho
Une autre utilisation des sous-expressions est l'extraction d'une partie de la correspondance si elle existe, c'est souvent utilisé conjointement avec les séquences, qui sont abordées plus loin.


Vous pouvez aussi utiliser le résultat d'une sous-expression pour ce qui est appelé une rétro-référence. Une rétro-référence est obtenue en utilisant un chiffre 'antislashé', seulement un chiffre différent de zéro, cela vous permet neuf rétro-références.
La rétro-référence renverra la correspondance à la sous-expression désignée (sauf que {article_contents_1} correspond à un caractère nul). Pour trouver le nombre de sous-expressions, comptez les parenthèses gauches à partir de la gauche.

L'utilisation des rétro-références est un peu limitée, d'autant plus que vous en avez seulement neuf, mais en certaines rares occasions vous pourriez en avoir besoin. Notez que certaines implémentations d'expressions régulières peuvent utiliser des nombres de plusieurs chiffres tant qu'ils ne commencent pas par 0.

Ensuite ce sont les alternances qui vous permettent une correspondance à beaucoup de mots, le caractère d'alternative est

|
Une utilisation type est :

Bill|Linus|Steve|Larry
correspondrait à Bill, Linus, Steve ou Larry, et la combinaison avec des sous-expressions et des quantificateurs nous permet de faire :

cow(ard|age|boy|l)?
qui renverra chacun des mots suivants, et aucun autre.

cow
coward
cowage
cowboy
cowl
J'ai mentionné plus tôt dans l'article que l'expression n'a pas à correspondre entièrement pour être couronnée de succès, cela peut arriver quand vous utilisez des sous-expressions mélangées à des alternances. Par exemple

((Donald|Dolly) Duck)|(Scrooge McDuck)
Comme vous le voyez, seulement la sous-expression supérieure gauche ou droite pourra correspondre, mais pas les deux. C'est parfois pratique quand vous voulez exécuter un motif complexe dans une sous-expression, et s'il échoue, en essayer un autre.

Séquences

Enfin nous avons les séquences qui définissent une suite de caractères à faire correspondre, parfois vous ne voulez pas directement une correspondance à un mot, mais plutôt à quelque chose qui lui ressemble. Les caractères de séquence sont

[ et ]
Chaque caractère mis à l'intérieur des crochets de séquence est traité comme caractère littéral, même les méta-caractères. Les seuls caractères spéciaux sont - qui désigne un ensemble de caractères, et ^ qui est utilisé pour exclure une séquence. La séquence est assez semblable à l'alternance, la similitude est que un seul des éléments inscrits correspondra. Par exemple

[a-z]
correspondra à toute lettre minuscule non accentuée qui est dans l'alphabet (de a à z). Une autre séquence commune est

[a-zA-Z0-9]
qui correspond à n'importe quel caractère non accentué minuscule ou majuscule dans l'alphabet, ainsi que les chiffres. Les séquences sont aussi mélangées avec des quantificateurs et des assertions pour produire des recherches plus complexes. Par exemple

<[a-zA-Z]+>
Correspond à tous les mots complets. Cela correspondra à

cow
Linus
regular
expression
mais ne correspondra pas à

200
x-files
C++
Maintenant, et si vous aviez voulu trouver n'importe quoi sauf des mots, l'expression

[^a-zA-Z0-9]+
trouverait n'importe quelles séquences de caractères qui ne sont pas tirés de l'alphabet ou constitués de chiffres.

Quelques implémentations d'expressions régulières vous permettent d'utiliser des abréviations de séquences couramment utilisées, ce sont:

\d, un chiffre [0-9]
\D, un non-chiffre [^0-9]
\w, un mot (alphanumérique) [A-zA-Z0-9]
\W, un non-mot [^a-zA-Z0-9]
\s, un espace [ \t\n\r\f]
\S, un non-espace [^ \t\n\r\f]

Caractères de remplacement/jokers

Pour les personnes qui ont quelques connaissances sur les caractères de remplacement, je donnerai une brève explication sur la façon de les convertir en expressions régulières. Après la lecture de cet article, vous avez probablement vu les ressemblances avec les caractères de remplacement. Par exemple

*.jpg
renvoie n'importe quel texte qui finit par .jpg. Vous pouvez aussi spécifier des crochets avec des caractères, par exemple

*.[ch]pp
correspond à n'importe quel texte qui termine par .cpp ou .hpp. Tout cela est très semblable aux expressions régulières.

Conversion de l'opérateur *

Dans les jokers, le * signifie une correspondance à zéro ou plus, de n'importe quel caractère. Comme nous l'avons appris, nous le faisons sous forme d'expression régulière avec le signe de ponctuation '.' et le quantificateur *. Cela donne

.*
Rappelez-vous aussi de convertir les signes de ponctuation '.' des jokers avec l'antislash.

Conversion de l'opérateur ?

Le ? signifie une correspondance à n'importe quel caractère, mais une correspondance à vraiment quelque chose, c'est exactement ce que le signe de ponctuation '.' fait.

Conversion de l'opérateur [ ]

Les [ ] peuvent être utilisés tels quels puisqu'ils ont la même signification dans les jokers que dans les expressions régulières.

Ceci nous laissent avec :
Remplacez chaque * par .*
Remplacez chaque ? par .
Laissez les crochets comme ils sont
Remplacez tous les caractères qui sont des méta-caractères par leur variante avec l'antislash.

Exemples


*.jpg
serait converti en

.*\.jpg


ez*.[ch]pp
serait converti en

ez.*\.[ch]pp
ou bien

ez.*\.(cpp|hpp)

Exemples

Pour vraiment parvenir à connaître les expressions régulières j'ai laissé sur cette page, certaines des expressions les plus couramment utilisées. Étudiez-les, expérimentez-les et essayez de comprendre exactement ce qu'elles font.

Validité de courrier électronique, correspondra seulement aux adresses électroniques qui sont valables, par exemple user@host.com

[a-z0-9_-]+(\.[a-z0-9_-]+)*@[a-z0-9_-]+(\.[a-z0-9_-]+)+

Validité de courrier électronique #2, correspond aux adresses électroniques comprenant un nom, par exemple "Joe Doe "

("?[a-zA-Z]+"?[ \t]*)+\<[a-z0-9_-]+(\.[a-z0-9_-]+)*@[a-z0-9_-]+(\.[a-z0-9_-]+)+\>

Validité de protocole, correspond aux protocoles web basés sur http://, ftp:// ou https://

[a-z]+://

Inclusion en C/C++, correspond aux déclarations d'inclusion de fichier valables en C/C++ .

^#include[ \t]+[<"][^>"]+[">]

Commentaires C++ en fin de ligne

//.+$

Commentaires C/C++ sur plusieurs lignes, elle a un défaut, pouvez-vous le découvrir ?

/\*[^*]*\*/

Nombres à virgule flottante, correspond aux nombres simples à virgule flottante de type 1.2 et 0.5

-?[0-9]+\.[0-9]+

Nombres hexadécimaux, correspond aux nombres hexa de style C/C++, 0xcafebabe

0x[0-9a-fA-F]+

Utilitaires

Il existe plusieurs utilitaires exploitant les expressions régulières. Je laisse une liste de certains d'entre eux avec une courte description :

grep

Grep recherche dans les fichiers indiqués les lignes correspondant au motif donné. Il peut aussi être utilisé pour trouver les fichiers contenant un motif spécifique, par exemple :

grep -E "cow|vache" * >/dev/null && echo "Found a cow"

C'est un utilitaire plutôt commun sur les distributions Linux, mais si vous ne l'avez pas vous pouvez obtenir une version sur la page GNU

Une petite astuce est d'activer les expressions régulières étendues avec l'option -E, sinon la plupart des méta-caractères expliqués dans cet article ne fonctionnent pas.

sed

Sed est un éditeur de flux. Un éditeur de flux est utilisé pour exécuter des transformations basiques de texte sur un flux séquentiel de données.

C'est un utilitaire plutôt commun sur les distributions Linux, mais si vous ne l'avez pas vous pouvez trouver une version sur la page GNU

gawk

Gawk est l'implémentation du projet GNU du langage de programmation AWK. Elle est conforme à la définition du langage édictée par le Standard POSIX 1003.2 des Langages de Commandes et Utilitaires.

C'est un utilitaire plutôt commun sur les distributions Linux, mais si vous ne l'avez pas vous pouvez trouver une version sur la page GNU

[document édité ici]
Expressions régulières liens associés :

Regular Expressions and NP-Completeness
Equivalence of Regular Expressions and Finite Automata
Perl Regular Expression Tutorial
[NdT : fr.wikipedia]