Introduction aux expressions régulières
Introduction
Les expressions régulières (ou regex) sont des séquences de caractères qui décrivent un modèle de recherche dans une chaîne de caractères. Elles sont utilisées dans de nombreux langages de programmation pour rechercher, extraire et manipuler des données textuelles. Les regex permettent de décrire avec précision des modèles de recherche complexes, tels que des adresses e-mail ou des numéros de téléphone, et peuvent être bien plus rapides et efficaces que de parcourir manuellement chaque ligne de texte pour extraire des informations spécifiques.
Dans cet article, nous allons explorer les différentes fonctionnalités des expressions régulières, en nous concentrant sur les exemples pratiques en Python, Bash et JavaScript. Nous allons commencer par les bases des expressions régulières, puis progresser vers des techniques plus avancées comme les lookaround, les quantificateurs et l’alternance. Enfin, nous examinerons comment utiliser les expressions régulières pour effectuer des substitutions et modifier le comportement de recherche en utilisant des drapeaux.
Que vous soyez un développeur débutant ou expérimenté, cet article devrait vous fournir des bases solides pour comprendre et utiliser les expressions régulières dans vos projets.
Voici un exemple d’expression régulière simple:
|
|
Dans cet exemple, l’expression régulière abc+ correspond à la chaîne “ab” suivie d’un ou plusieurs caractères “c”. Cela signifie que l’expression régulière correspondra à “abc”, “abcc”, “abccc”, etc.
Les classes de caractères
Les classes de caractères (ou character classes) sont des ensembles de caractères qui peuvent être utilisés pour décrire des modèles de recherche spécifiques. Les classes de caractères sont spécifiées en utilisant des crochets ([]
) et permettent de décrire un seul caractère qui correspond à n’importe quel caractère de l’ensemble spécifié.
Voici quelques exemples de classes de caractères :
[abc]
: correspond à n’importe quel caractère qui est soit ‘a’, ‘b’, ou ‘c’[a-z]
: correspond à n’importe quel caractère qui est une lettre minuscule[A-Z]
: correspond à n’importe quel caractère qui est une lettre majuscule[0-9]
: correspond à n’importe quel caractère qui est un chiffre.
: correspond à n’importe quel caractère
Les classes de caractères peuvent également être négatives, ce qui signifie qu’elles correspondent à tout caractère qui n’appartient pas à l’ensemble spécifié. Les classes de caractères négatives sont spécifiées en utilisant le symbole ^
à l’intérieur des crochets.
Voici un exemple de classe de caractères négative :
[^0-9]
: correspond à n’importe quel caractère qui n’est pas un chiffre
Il est également possible de combiner des classes de caractères en utilisant des parenthèses pour créer des groupes. Les groupes peuvent être combinés avec des quantificateurs pour rechercher des motifs de texte plus complexes.
Voici un exemple de groupe de classes de caractères :
([a-z]|[A-Z])
: correspond à n’importe quel caractère qui est une lettre, qu’elle soit majuscule ou minuscule
En Python, les classes de caractères peuvent être utilisées en utilisant la fonction re.search()
:
|
|
En JavaScript, les classes de caractères peuvent être utilisées en utilisant la méthode test()
de l’objet RegExp :
|
|
En Bash, les classes de caractères peuvent être utilisées en utilisant l’outil grep
:
|
|
Ancres
Les ancres sont des métacaractères qui permettent de délimiter des motifs de recherche en spécifiant une position précise dans le texte. Les deux ancres les plus couramment utilisées sont ^
et $
.
L’ancre ^
correspond au début d’une chaine de caractère, tandis que l’ancre $
correspond à la fin d’une chaine de caractère.
Ils peuvent également correspondre au début et à la fin d’une ligne si le flag multiligne m
est activé. Nous reviendrons sur la notion de flag plus tard dans l’article.
Il existe également deux autres ancres, \b
et \B
, qui correspondent respectivement au début ou à la fin d’un mot.
En voici quelques exemples :
\bcode
: correspond à toutes les occurrences du mot “code” en début de mottuto\B
: correspond à toutes les occurrences du mot “tuto” qui ne se terminent pas par une lettre
Voici quelques exemples :
^Bonjour
: correspond à toutes les chaines de caractères qui commencent par “Bonjour”Au revoir$
: correspond à toutes les chaines de caractères qui se terminent par “Au revoir”
En Python, les ancres peuvent être utilisées en utilisant la fonction re.search()
:
|
|
En JavaScript, les ancres peuvent être utilisées en utilisant la méthode test() de l’objet RegExp
:
|
|
En Bash, les ancres peuvent être utilisées en utilisant l’outil grep
:
|
|
Remarque, en bash, le grep s’applique sur chaque ligne, il n’y a donc pas de flag multiligne m
.
Les caractères échappés / escaped characters
Certains caractères ont un sens particulier dans les expressions régulières et ne peuvent pas être utilisés directement. Pour les utiliser dans une expression régulière, ils doivent être échappés en les préfixant avec un caractère d’échappement (\
). Voici quelques exemples de caractères échappés couramment utilisés :
\.
: correspond à un point littéral\\
: correspond à un backslash littéral\d
: correspond à n’importe quel chiffre\D
: correspond à n’importe quel caractère qui n’est pas un chiffre\w
: correspond à n’importe quel caractère alphanumérique, y compris le soulignement\W
: correspond à n’importe quel caractère qui n’est pas alphanumérique ni souligné\s
: correspond à n’importe quel espace blanc (espace, tabulation, retour à la ligne, etc.)\S
: correspond à n’importe quel caractère qui n’est pas un espace blanc\b
: correspond au début d’un mot\B
: correspond à la fin d’un mot
En Python, les caractères échappés peuvent être utilisés en utilisant la fonction re.search()
:
|
|
En JavaScript, les caractères échappés peuvent être utilisés en utilisant la méthode test() de l’objet RegExp
:
|
|
En Bash, les caractères échappés peuvent être utilisés en utilisant l’outil grep :
|
|
-o: affiche uniquement les caractères trouvés
-P: le pattern est une expression régulière perl.
Quantifiers & Alternation
Les quantificateurs sont des symboles qui permettent de spécifier combien de fois un élément doit apparaître dans une expression régulière. Les quantificateurs les plus couramment utilisés sont les suivants :
*
: correspond à zéro ou plusieurs occurrences de l’élément précédent.+
: correspond à une ou plusieurs occurrences de l’élément précédent.?
: correspond à zéro ou une occurrence de l’élément précédent.{n}
: correspond à exactement n occurrences de l’élément précédent.{n,}
: correspond à au moins n occurrences de l’élément précédent.{n,m}
: correspond à entre n et m occurrences de l’élément précédent.
L’alternance est un autre concept important en expressions régulières qui permet de spécifier plusieurs alternatives pour un même élément. L’alternance est spécifiée en utilisant le symbole |
, qui signifie “ou”.
Voici un exemple de l’utilisation des quantificateurs et de l’alternance en Python :
|
|
Dans cet exemple, l’expression régulière "q.*?k|fox|dog"
recherche toutes les occurrences qui correspondent soit à "q.*?k"
, soit à "fox"
, soit à "dog"
. Les .*?
correspondent à n’importe quel caractère qui apparaît entre les lettres "q"
et "k"
, tandis que l’alternance |
permet de spécifier les alternatives "fox"
et "dog"
.
Voici un exemple d’utilisation des quantificateurs et de l’alternance en JavaScript :
|
|
Dans cet exemple, l’expression régulière /q.*?k|fox|dog/g
recherche toutes les occurrences qui correspondent soit à "q.*?k"
, soit à "fox"
, soit à "dog"
. Le .*?
correspond à n’importe quel caractère qui apparaît entre les lettres "q"
et "k"
, tandis que l’alternance |
permet de spécifier les alternatives "fox"
et "dog"
. Le flag g
permet de rechercher toutes les occurrences dans le texte.
Voici un exemple d’utilisation des quantificateurs et de l’alternance en Bash :
|
|
Dans cet exemple, l’expression régulière "q.*?k|fox|dog"
recherche toutes les occurrences qui correspondent soit à "q.*?k"
, soit à "fox"
, soit à "dog"
. Les .*?
correspondent à n’importe quel caractère qui apparaît entre les lettres "q"
et "k"
, tandis que l’alternance | permet de spécifier les alternatives "fox"
et "dog"
.
L’option -E signifie “utiliser des expressions régulières étendues” au lieu d’utiliser des expressions régulières de base. Les expressions régulières étendues offrent des fonctionnalités plus avancées que les expressions régulières de base, telles que la possibilité d’utiliser des quantificateurs tels que +, ? et {}, ou encore l’alternance |.
L’option -o signifie “afficher uniquement les correspondances”. Cette option permet d’afficher uniquement les parties de la chaîne d’entrée qui correspondent à l’expression régulière, au lieu d’afficher toute la chaîne d’entrée avec les correspondances surlignées.
Groupes et références
Les groupes et références sont des fonctionnalités avancées des expressions régulières qui permettent de capturer des sous-parties de l’expression régulière et de les réutiliser dans la même expression régulière ou dans du code.
Un groupe est défini en entourant une partie de l’expression régulière avec des parenthèses. Les groupes peuvent être utilisés pour capturer des sous-parties de la chaîne de caractères qui correspondent à l’expression régulière. Par exemple, l’expression régulière "(\d{2})-(\d{2})-(\d{4})"
capture trois groupes correspondant à la date sous la forme "jj-mm-aaaa"
. Chaque groupe peut ensuite être référencé en utilisant la syntaxe \N, où N est le numéro du groupe.
Voici un exemple de groupe utilisé pour capturer des adresses e-mail dans un texte :
|
|
Dans cet exemple, le groupe est utilisé pour capturer l’adresse e-mail complète, composée de trois parties : le nom d’utilisateur, le nom de domaine et l’extension. Le +
après chaque classe de caractères signifie qu’il y a au moins un caractère qui correspond à cette classe.
Voici des exemples d’expressions régulières utilisant des groupes et références dans Python, JavaScript et Bash :
|
|
|
|
|
|
|
|
Explication de la regex (?P<day>\d{1,2})[/\- ](?P<month>\w{2})[/\- ](?P<year>\d{2,4})
:
(?<day>\d{1,2})
: Cela utilise la syntaxe(?<nom>pattern)
pour créer un groupe nommé"day"
.\d{1,2}
signifie qu’il y aura un ou deux chiffres.[/\- ]
: Correspond à l’un des caractères suivants: /, - ou un espace.(?<month>\w{2})
: Cela utilise la syntaxe(?<nom>pattern)
pour créer un groupe nommé"month"
.\w{2}
signifie qu’il y aura exactement deux caractères alphanumériques.[/\- ]
: Correspond à l’un des caractères suivants: /, - ou un espace.(?<year>\d{2,4})
: Cela utilise la syntaxe(?<nom>pattern)
pour créer un groupe nommé"year"
.\d{2,4}
signifie qu’il y aura deux, trois ou quatre chiffres.
|
|
|
|
Ce code extrait des dates d’un texte donné en utilisant une expression régulière pour identifier les différents formats de dates possibles (jour/mois/année), stockées dans une variable regex
.
Le code utilise ensuite la commande grep
pour trouver toutes les occurrences des expressions régulières correspondantes dans la variable text
, puis utilise la commande sed
pour extraire les différentes parties de la date (jour, mois, année) de chaque occurrence et les stocker dans des variables.
Finalement, il affiche les dates extraites dans un message.
|
|
lookaround
Bien sûr, voici la partie sur les lookaround en incluant les lookbehind positif et négatif :
Les lookaround en expressions régulières sont des opérations de vérification de la présence d’une expression à gauche ou à droite de la position actuelle, sans faire partie de la correspondance globale. Ils permettent de spécifier des conditions pour lesquelles une expression régulière doit être valide ou non.
Il y a deux types de lookaround: les lookaheads (regard en avant) et les lookbehinds (regard en arrière). Les lookaheads permettent de spécifier des conditions à vérifier après la position actuelle, tandis que les lookbehinds permettent de spécifier des conditions à vérifier avant la position actuelle.
Les lookaheads positifs ((?=expression)
) vérifient que l’expression se trouve après la position actuelle, sans inclure cette expression dans la correspondance globale. Les lookaheads négatifs ((?!expression)
) vérifient le contraire : ils vérifient que l’expression ne se trouve pas après la position actuelle.
Voici un exemple d’utilisation des lookaheads en Python pour trouver tous les mots qui sont suivis par le mot “fox”:
|
|
Dans cet exemple, l’expression régulière \b\w+(?= fox)
recherche tous les mots (\b\w+
) qui sont suivis par le mot “fox” ((?= fox)
). Le \b
correspond à une limite de mot. L’utilisation du lookahead permet de vérifier la présence du mot “fox” après la position actuelle, mais sans l’inclure dans la correspondance globale.
Les lookbehinds positifs ((?<=expression)
) vérifient que l’expression se trouve avant la position actuelle, sans inclure cette expression dans la correspondance globale. Les lookbehinds négatifs ((?<!expression)
) vérifient le contraire : ils vérifient que l’expression ne se trouve pas avant la position actuelle.
Voici un exemple d’utilisation des lookbehinds en JavaScript pour trouver tous les nombres qui sont précédés du signe “$”:
|
|
Dans cet exemple, l’expression régulière /(?<=\$)\d+\.\d{2}/g
recherche tous les nombres (\d+\.\d{2}
) qui sont précédés du signe “$” ((?<=\$)
). L’utilisation du lookbehind permet de vérifier la présence du signe “$” avant la position actuelle, mais sans l’inclure dans la correspondance globale.
Enfin, les lookbehinds ne sont pas supportés dans toutes les implémentations d’expressions régulières. Par exemple, les lookbehinds ne sont pas supportés dans les expressions régulières JavaScript avant la version ECMAScript 2018.
Flags
En plus des symboles et des concepts que nous avons déjà examinés, les expressions régulières peuvent être accompagnées de “flags” ou “options”. Les flags sont des indicateurs qui modifient la façon dont les expressions régulières fonctionnent. Les trois flags les plus couramment utilisés sont les suivants :
i
: ce flag rend la recherche insensible à la casse. Cela signifie que la recherche correspondra à des lettres majuscules ou minuscules indifféremment. Par exemple, l’expression régulière/hello/i
correspondra à “Hello”, “hello” et “hElLo”.g
: ce flag signifie “global” et permet de rechercher toutes les occurrences d’une correspondance dans la chaîne de texte. Par défaut, une expression régulière ne correspondra qu’à la première occurrence de la correspondance. Par exemple, l’expression régulière/hello/g
correspondra à toutes les occurrences de “hello” dans le texte.m
: ce flag signifie “multiline” et permet à une expression régulière de correspondre à des chaînes de texte qui contiennent plusieurs lignes. Sans ce flag, l’expression régulière considérera la chaîne de texte comme une seule ligne.
Voici un exemple de l’utilisation du flag m
en Python :
|
|
Le flag re.MULTILINE
(ou re.M
) est un flag de compilation qui modifie le comportement de certaines classes de caractères et de certains quantificateurs pour qu’ils fonctionnent sur plusieurs lignes. Par exemple, sans le flag re.MULTILINE
, l’expression régulière ^
ne correspond qu’au début de la chaîne. Avec le flag re.MULTILINE
, l’expression régulière ^
correspond également au début de chaque ligne.
Dans cet exemple, l’expression régulière ^t\w+
recherche toutes les chaînes qui commencent par un “t” suivi de un ou plusieurs caractères de mot (\w+
), en utilisant le flag re.MULTILINE
. Le flag re.MULTILINE
permet de rechercher la chaîne the
dans toutes les lignes.
Voici un exemple d’utilisation du flag g
en JavaScript :
|
|
Dans cet exemple, le flag g
est utilisé pour rechercher toutes les occurrences de la correspondance “hello” dans le texte.
Voici un exemple d’utilisation du flag i en Bash :
|
|
Dans cet exemple, la commande grep
recherche toutes les occurrences de "FOX"
dans la chaîne $text
, en ignorant la distinction entre majuscules et minuscules grâce au flag -i
. Le flag -o
permet d’afficher uniquement les parties de la chaîne d’entrée qui correspondent à l’expression régulière, au lieu d’afficher toute la chaîne d’entrée avec les correspondances surlignées.