Expressions régulières
Mise à jour :
Les expressions régulières, ou regex, c’est un peu comme une langue secrète pour communiquer avec vos données textuelles. Si vous vous êtes déjà demandé comment extraire des adresses e-mail d’un document, vérifier un numéro de téléphone ou remplacer des mots spécifiques dans un texte, les regex sont là pour vous simplifier la vie.
Avec Python, manipuler les regex est un jeu d’enfant grâce au module intégré
re
. Que vous soyez développeur débutant ou expérimenté, apprendre à utiliser
les regex vous ouvrira de nouvelles perspectives pour traiter des chaînes de
caractères de manière rapide et efficace.
Mais pas de panique, je sais que les regex peuvent sembler un peu intimidantes
au départ. Entre les astérisques, les parenthèses, et les mystérieuses séquences
comme \d
ou \w
, on peut vite se sentir perdu. Dans ce guide, je vais vous
accompagner étape par étape, avec des explications claires et des exemples
concrets. Vous verrez, c’est beaucoup plus simple qu’il n’y paraît !
Prêt à plonger dans l’univers fascinant des regex en Python ? Alors, allons-y !
Premier pas
Bonne nouvelle : vous n’avez rien à installer pour utiliser les expressions
régulières en Python ! Le module re
est intégré par défaut dans la
bibliothèque standard de Python. En gros, il est prêt à l’emploi dès que vous
installez Python.
Avant toute chose, on importe simplement le module re
dans notre script. Voici
comment faire :
import re
Et voilà, vous êtes prêt à travailler avec des regex ! Maintenant, passons à l’essentiel : écrire et tester des motifs.
Une regex, c’est un peu comme un détective textuel. Par exemple, si vous voulez trouver le mot “Python” dans une phrase, vous pouvez utiliser cette expression régulière :
import re
# La chaîne de texte où cherchertexte = "J'apprends Python avec passion."
# Rechercher le mot "Python"resultat = re.search("Python", texte)
if resultat: print("Mot trouvé !")else: print("Mot non trouvé.")
Quand vous exécutez ce script, il affichera “Mot trouvé !” si la chaîne contient “Python”. Facile, non ?
Si vous voulez que votre recherche ignore les majuscules et minuscules, ajoutez
l’option re.IGNORECASE
:
resultat = re.search("python", texte, re.IGNORECASE)
Les bases des regex
Pour vraiment comprendre les expressions régulières, il faut se familiariser avec les bases. Les regex utilisent des caractères spéciaux et des règles qui permettent de rechercher, capturer ou manipuler du texte. Pas d’inquiétude, je vais tout vous expliquer simplement !
Les regex reposent sur des symboles qui ont des significations précises. Voici les principaux que vous rencontrerez souvent :
-
Le point (
.
) Correspond à n’importe quel caractère sauf une nouvelle ligne (\n
). Exemple :import retexte = "chat"print(re.search("c.a.", texte)) # Renvoie None car "chat" ne correspond pas à "c.a." -
Le symbole d’ancrage début (
^
) Vérifie si un motif est au début de la chaîne. Exemple :texte = "Python est génial"print(re.match("^Python", texte)) # Motif trouvé au début -
Le symbole d’ancrage fin (
$
) Vérifie si un motif est à la fin de la chaîne. Exemple :texte = "J'adore le Python"print(re.search("Python$", texte)) # Motif trouvé à la fin -
Les crochets (
[]
) Spécifient un ensemble de caractères possibles. Exemple :texte = "chat"print(re.search("[aeiou]", texte)) # Trouve "a", une voyelle -
Le tiret dans les crochets (
[a-z]
) Définit une plage de caractères. Exemple :texte = "Mon mot de passe est sûr123"print(re.search("[0-9]", texte)) # Trouve un chiffre -
L’étoile (
*
) Correspond à zéro ou plusieurs occurrences du caractère précédent. Exemple :texte = "baaa"print(re.search("ba*", texte)) # Trouve "baaa" -
Le plus (
+
) Correspond à une ou plusieurs occurrences du caractère précédent. Exemple :texte = "baaa"print(re.search("ba+", texte)) # Trouve aussi "baaa" -
Le point d’interrogation (
?
) Correspond à zéro ou une occurrence du caractère précédent. Exemple :texte = "color"print(re.search("colou?r", texte)) # Trouve "color" ou "colour"
Classes de caractères et métasymboles
Les classes de caractères et les métasymboles permettent de créer des expressions régulières plus flexibles et précises. Ils définissent des ensembles de caractères ou des motifs spécifiques que vous pouvez utiliser dans vos recherches.
Les classes de caractères
Les classes de caractères permettent de définir un ensemble de caractères à
matcher. Elles sont encadrées par des crochets []
.
-
Caractères individuels Correspondent à l’un des caractères définis dans les crochets. Exemple :
import retexte = "chat"motif = r"[abc]"resultat = re.search(motif, texte)print(resultat.group()) # Trouve "c" -
Plages de caractères Utilisez un tiret
-
pour définir une plage. Exemple :import retexte = "abcd"motif = r"[a-c]"resultat = re.findall(motif, texte)print(resultat) # ['a', 'b', 'c'] -
Exclusion avec
^
Le^
en début de crochets exclut les caractères spécifiés. Exemple :import retexte = "123abc"motif = r"[^0-9]"resultat = re.findall(motif, texte)print(resultat) # ['a', 'b', 'c'] -
Combinaison de caractères et plages Vous pouvez combiner des plages et des caractères individuels. Exemple :
import retexte = "a1b2c3"motif = r"[a-z1-3]"resultat = re.findall(motif, texte)print(resultat) # ['a', '1', 'b', '2', 'c', '3']
Les métasymboles
Les métasymboles représentent des motifs spécifiques.
-
Le point (
.
) Correspond à n’importe quel caractère sauf une nouvelle ligne. Exemple :import retexte = "abc\ndef"motif = r"a.c"resultat = re.search(motif, texte)print(resultat.group()) # "abc" -
Le backslash (
\
) Utilisé pour échapper un caractère spécial ou pour indiquer une classe prédéfinie. Exemple :import retexte = "Le coût est de 100$"motif = r"100\$"resultat = re.search(motif, texte)print(resultat.group()) # "100$" -
Le pipe (
|
) Correspond à une alternative (ou logique). Exemple :import retexte = "J'aime les pommes ou les oranges"motif = r"pommes|oranges"resultat = re.search(motif, texte)print(resultat.group()) # "pommes"
Classes de caractères prédéfinies
Ces classes simplifient les recherches courantes.
-
\d
Correspond à un chiffre (0-9). Exemple :import retexte = "Il y a 42 pommes"motif = r"\d+"resultat = re.search(motif, texte)print(resultat.group()) # "42" -
\D
Correspond à tout sauf un chiffre. Exemple :import retexte = "42 pommes"motif = r"\D+"resultat = re.search(motif, texte)print(resultat.group()) # " pommes" -
\w
Correspond à un caractère alphanumérique (a-z, A-Z, 0-9, et_
). Exemple :import retexte = "Python_3 est génial !"motif = r"\w+"resultat = re.findall(motif, texte)print(resultat) # ['Python_3', 'est', 'génial'] -
\W
Correspond à tout sauf un caractère alphanumérique. Exemple :import retexte = "Python_3 est génial !"motif = r"\W+"resultat = re.findall(motif, texte)print(resultat) # [' ', ' ', ' !'] -
\s
Correspond à un espace, une tabulation ou une nouvelle ligne. Exemple :import retexte = "Python est génial"motif = r"\s"resultat = re.findall(motif, texte)print(resultat) # [' ', ' '] -
\S
Correspond à tout sauf un espace. Exemple :import retexte = "Python est génial"motif = r"\S+"resultat = re.findall(motif, texte)print(resultat) # ['Python', 'est', 'génial']
Les quantificateurs
Les quantificateurs sont des outils puissants des expressions régulières qui permettent de définir combien de fois un motif peut se répéter. Ils sont essentiels pour matcher des motifs variables, comme des séquences de chiffres ou des mots avec des longueurs différentes.
Les principaux quantificateurs
-
L’astérisque (
*
) Correspond à zéro ou plusieurs occurrences du caractère ou du groupe précédent. Exemple :import retexte = "hellooo"motif = r"lo*"resultat = re.search(motif, texte)print(resultat.group()) # "loo"Ici, le motif capture “l” suivi de zéro ou plusieurs “o”.
-
Le plus (
+
) Correspond à une ou plusieurs occurrences du caractère ou du groupe précédent. Exemple :import retexte = "hellooo"motif = r"lo+"resultat = re.search(motif, texte)print(resultat.group()) # "looo"Contrairement à
*
, le motif échoue si aucune occurrence n’est trouvée. -
Le point d’interrogation (
?
) Correspond à zéro ou une occurrence du caractère ou du groupe précédent. Exemple :import retexte = "color" # ou "colour"motif = r"colou?r"resultat = re.search(motif, texte)print(resultat.group()) # "color" ou "colour" -
Les accolades (
{n}
ou{n,m}
) Correspondent à un nombre précis ou une plage d’occurrences.{n}
: exactementn
occurrences.{n,}
: au moinsn
occurrences.{n,m}
: entren
etm
occurrences.
Exemple :
import retexte = "aaaaa"motif = r"a{2,4}"resultat = re.search(motif, texte)print(resultat.group()) # "aaaa"
Quantificateurs “gourmands” et “non-gourmands”
Par défaut, les quantificateurs sont gourmands, c’est-à-dire qu’ils
capturent autant de caractères que possible. Pour les rendre non-gourmands,
ajoutez un point d’interrogation ?
juste après le quantificateur.
Exemple :
import re
texte = "<tag>contenu</tag>"motif_gourmand = r"<.*>"motif_non_gourmand = r"<.*?>"
resultat_gourmand = re.search(motif_gourmand, texte)resultat_non_gourmand = re.search(motif_non_gourmand, texte)
print("Gourmand :", resultat_gourmand.group()) # "<tag>contenu</tag>"print("Non-gourmand :", resultat_non_gourmand.group()) # "<tag>"
Combinaisons pratiques
-
Capturer une adresse IP : Une adresse IP se compose de 4 groupes de 1 à 3 chiffres séparés par des points.
import retexte = "Mon IP est 192.168.1.1"motif = r"(\d{1,3}\.){3}\d{1,3}"resultat = re.search(motif, texte)if resultat:print("IP trouvée :", resultat.group()) -
Trouver des mots répétés :
import retexte = "Je suis très très content."motif = r"\b(\w+)\s+\1\b"resultat = re.search(motif, texte)if resultat:print("Mot répété trouvé :", resultat.group()) -
Valider un numéro de téléphone :
import retexte = "Mon numéro est 06-12-34-56-78"motif = r"\d{2}(-\d{2}){4}"resultat = re.search(motif, texte)if resultat:print("Numéro trouvé :", resultat.group())
Les fonctions du module re
Le module re
de Python propose plusieurs fonctions très pratiques pour
travailler avec les expressions régulières. Chaque fonction a un rôle précis
et vous permet de rechercher, remplacer ou diviser des chaînes de caractères
efficacement.
Fonction re.match()
La fonction re.match()
vérifie si un motif apparaît au début d’une chaîne.
Si ce n’est pas le cas, elle retourne None
.
Exemple simple :
import re
texte = "Python est génial"motif = r"Python"
resultat = re.match(motif, texte)if resultat: print("Match trouvé :", resultat.group())else: print("Aucun match trouvé")
Limitation : Si le motif n’est pas au début de la chaîne, il ne sera pas trouvé.
Fonction re.search()
Contrairement à re.match()
, la fonction re.search()
recherche le motif
n’importe où dans la chaîne.
Exemple :
import re
texte = "J'adore le Python"motif = r"Python"
resultat = re.search(motif, texte)if resultat: print("Match trouvé :", resultat.group())else: print("Aucun match trouvé")
Ici, le mot “Python” est trouvé même s’il n’est pas au début de la chaîne.
Fonction re.findall()
La fonction re.findall()
retourne une liste contenant toutes les
occurrences correspondant au motif.
Exemple :
import re
texte = "123 456 789"motif = r"\d+"
resultat = re.findall(motif, texte)print("Occurrences trouvées :", resultat)
Sortie :
Occurrences trouvées : ['123', '456', '789']
Fonction re.finditer()
C’est une variante de re.findall()
, mais elle retourne un itérateur au
lieu d’une liste. Cet itérateur contient des objets match que vous pouvez
manipuler.
Exemple :
import re
texte = "Bonjour Python, au revoir Python"motif = r"Python"
resultats = re.finditer(motif, texte)for match in resultats: print("Match trouvé à la position :", match.start(), "-", match.end())
Fonction re.sub()
La fonction re.sub()
permet de remplacer un motif par une autre chaîne.
Exemple :
import re
texte = "Python est génial, Python est puissant"motif = r"Python"remplacement = "Java"
resultat = re.sub(motif, remplacement, texte)print(resultat)
Sortie :
Java est génial, Java est puissant
Fonction re.split()
La fonction re.split()
découpe une chaîne en fonction d’un motif et retourne
une liste des segments.
Exemple :
import re
texte = "Un;deux;trois;quatre"motif = r";"
resultat = re.split(motif, texte)print(resultat)
Sortie :
['Un', 'deux', 'trois', 'quatre']
Fonction re.compile()
Vous pouvez “préparer” une regex pour la réutiliser plusieurs fois grâce à
re.compile()
. Cela peut aussi améliorer les performances.
Exemple :
import re
texte = "Python est génial. Python est puissant."motif = re.compile(r"Python")
resultats = motif.findall(texte)print("Occurrences trouvées :", resultats)
Travailler avec des groupes et des captures
Les groupes et les captures sont l’un des aspects les plus puissants des expressions régulières en Python. Ils permettent d’extraire des sous-parties précises d’un texte, comme un e-mail dans une phrase ou une date dans un journal.
Qu’est-ce qu’un groupe ?
Un groupe est une partie de l’expression régulière entourée de parenthèses ()
.
Ces parenthèses permettent de capturer et de manipuler des sous-chaînes
correspondant au motif.
Exemple simple :
import re
texte = "Mon numéro est 06-12-34-56-78"motif = r"(\d{2})-(\d{2})-(\d{2})-(\d{2})-(\d{2})"
resultat = re.search(motif, texte)if resultat: print("Match complet :", resultat.group()) # Match complet print("Groupe 1 :", resultat.group(1)) # Premier groupe print("Groupe 2 :", resultat.group(2)) # Deuxième groupe
Sortie :
Match complet : 06-12-34-56-78Groupe 1 : 06Groupe 2 : 12
Numérotation des groupes
Les groupes capturés sont numérotés automatiquement de gauche à droite, à partir de 1 (le groupe 0 correspond au motif complet).
Exemple avec plusieurs groupes :
import re
texte = "Date : 2024-12-01"motif = r"(\d{4})-(\d{2})-(\d{2})"
resultat = re.search(motif, texte)if resultat: print("Année :", resultat.group(1)) # 2024 print("Mois :", resultat.group(2)) # 12 print("Jour :", resultat.group(3)) # 01
Nommage des groupes
Pour rendre votre regex plus lisible, vous pouvez nommer vos groupes avec
(?P<nom>)
. Vous accéderez ensuite aux groupes avec leurs noms.
Exemple :
import re
texte = "Date : 2024-12-01"motif = r"(?P<annee>\d{4})-(?P<mois>\d{2})-(?P<jour>\d{2})"
resultat = re.search(motif, texte)if resultat: print("Année :", resultat.group("annee")) # 2024 print("Mois :", resultat.group("mois")) # 12 print("Jour :", resultat.group("jour")) # 01
Récupérer tous les groupes
Vous pouvez récupérer tous les groupes d’un match sous forme de tuple avec
groups()
.
Exemple :
import re
texte = "Date : 2024-12-01"motif = r"(\d{4})-(\d{2})-(\d{2})"
resultat = re.search(motif, texte)if resultat: print("Tous les groupes :", resultat.groups()) # ('2024', '12', '01')
Groupes non capturants
Parfois, vous voulez grouper sans capturer, par exemple pour appliquer un
quantificateur à un groupe sans l’enregistrer. Utilisez alors (?:...)
.
Exemple :
import re
texte = "apple banana apple"motif = r"(?:apple|banana)"
resultats = re.findall(motif, texte)print("Occurrences trouvées :", resultats) # ['apple', 'banana', 'apple']
Captures imbriquées
Vous pouvez imbriquer des groupes pour capturer des sous-parties plus précises.
Exemple :
import re
texte = "Coordonnées : (06) 12-34-56-78"motif = r"\((\d{2})\)\s(\d{2})-(\d{2})-(\d{2})-(\d{2})"
resultat = re.search(motif, texte)if resultat: print("Numéro complet :", resultat.group()) # Match complet print("Préfixe :", resultat.group(1)) # 06
Groupes alternatifs
Vous pouvez utiliser |
pour spécifier des alternatives au sein d’un groupe.
Exemple :
import re
texte = "J'aime les pommes ou les oranges"motif = r"(pommes|oranges)"
resultat = re.search(motif, texte)if resultat: print("Fruit trouvé :", resultat.group()) # pommes ou oranges
Utilisation pratique
-
Extraire un e-mail :
import retexte = "Contactez-nous à support@example.com"motif = r"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})"resultat = re.search(motif, texte)if resultat:print("E-mail trouvé :", resultat.group()) -
Extraire une URL :
import retexte = "Visitez https://www.example.com pour en savoir plus"motif = r"https?://[a-zA-Z0-9.-]+"resultat = re.search(motif, texte)if resultat:print("URL trouvée :", resultat.group())
Expressions régulières avancées
Maintenant que vous maîtrisez les bases des expressions régulières, il est temps de découvrir des fonctionnalités avancées qui rendent les regex encore plus puissantes. Dans ce chapitre, nous allons explorer les assertions, les lookarounds, et les regex optimisées.
Assertions : les ancres de position
Les assertions permettent de fixer des conditions sur la position d’un motif sans le capturer.
-
Mot entier (
\b
) Correspond à une limite de mot (début ou fin). Exemple :import retexte = "J'aime Python, pas Pythonesque"motif = r"\bPython\b"print(re.search(motif, texte)) # Trouve "Python" -
Non-mot entier (
\B
) Correspond à tout sauf une limite de mot. Exemple :import retexte = "Pythonesque est complexe"motif = r"Python\B"print(re.search(motif, texte)) # Trouve "Python" dans "Pythonesque"
Lookahead et Lookbehind : les lookarounds
Les lookarounds permettent de vérifier des motifs avant ou après une position sans les capturer.
-
Lookahead positif (
(?=...)
) Vérifie qu’un motif suit la position actuelle. Exemple :import retexte = "Python3 est génial"motif = r"Python(?=\d)"print(re.search(motif, texte)) # Trouve "Python" suivi d'un chiffre -
Lookahead négatif (
(?!...)
) Vérifie qu’un motif ne suit pas la position actuelle. Exemple :import retexte = "Python est génial"motif = r"Python(?!\d)"print(re.search(motif, texte)) # Trouve "Python" non suivi d'un chiffre -
Lookbehind positif (
(?<=...)
) Vérifie qu’un motif précède la position actuelle. Exemple :import retexte = "J'aime le Python"motif = r"(?<=le )Python"print(re.search(motif, texte)) # Trouve "Python" précédé de "le" -
Lookbehind négatif (
(?<!...)
) Vérifie qu’un motif ne précède pas la position actuelle. Exemple :import retexte = "J'aime Python, pas JavaPython"motif = r"(?<!Java)Python"print(re.search(motif, texte)) # Trouve "Python" non précédé de "Java"
Modifier le comportement des regex
-
Mode multi-lignes (
re.MULTILINE
) Le caractère^
correspond au début de chaque ligne, et$
à la fin de chaque ligne. Exemple :import retexte = "Python\nJava\nC++"motif = r"^Java"print(re.search(motif, texte, re.MULTILINE)) # Trouve "Java" en début de ligne -
Mode point étendu (
re.DOTALL
) Le point (.
) correspond également aux sauts de ligne (\n
). Exemple :import retexte = "Bonjour.\nComment ça va ?"motif = r".*"print(re.search(motif, texte, re.DOTALL).group()) # Capture tout, y compris les sauts de ligne -
Mode insensible à la casse (
re.IGNORECASE
) Les correspondances ignorent les majuscules et les minuscules. Exemple :import retexte = "PYTHON est génial"motif = r"python"print(re.search(motif, texte, re.IGNORECASE)) # Trouve "PYTHON"
Bonnes pratiques
Les expressions régulières sont puissantes, mais elles peuvent vite devenir un casse-tête si on les utilise mal. Dans ce chapitre, je vais partager avec vous quelques bonnes pratiques pour écrire des regex efficaces, ainsi que les erreurs courantes à éviter.
-
Privilégiez la simplicité Évitez les regex trop complexes. Une regex simple est plus facile à lire, à maintenir et à déboguer. Exemple :
Mauvais :
([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})Mieux :
\w+@\w+\.\w{2,} -
Ajoutez des commentaires Si votre regex devient trop complexe, utilisez le mode verbose (
re.VERBOSE
) pour ajouter des commentaires. Exemple :import remotif = re.compile(r"""\w+ # Partie avant l'@@ # Symbole @\w+\.\w+ # Domaine""", re.VERBOSE) -
Évitez les regex inutiles Parfois, une fonction Python standard est suffisante. Exemple :
Mauvais :
import retexte = "Python"if re.match(r"Python", texte):print("Mot trouvé")Mieux :
texte = "Python"if "Python" in texte:print("Mot trouvé") -
Utilisez des outils pour tester vos regex Des plateformes comme Regex101 ↗ vous aident à visualiser et tester vos regex.
-
Échappez les caractères spéciaux Si vous recherchez des caractères spéciaux (comme
.
ou*
), échappez-les avec\
. Exemple :import retexte = "Fichier.log"motif = r"\."print(re.search(motif, texte)) # Trouve le point littéral
Astuces pour le débogage
-
Utilisez
re.DEBUG
pour afficher des informations sur la regex. Exemple :import rere.compile(r"\d+", re.DEBUG) -
Découpez les regex complexes en sous-parties et testez-les indépendamment.
-
Visualisez les captures avec
resultat.groups()
ouresultat.groupdict()
pour comprendre ce qui est extrait.
Conclusion
Les expressions régulières sont un outil incroyablement puissant pour manipuler et analyser du texte en Python. Que ce soit pour valider des données, rechercher des motifs ou nettoyer des chaînes, elles vous permettent de gagner du temps et d’automatiser des tâches complexes.
Dans ce guide, nous avons exploré les bases, les fonctions du module re
, et
des techniques avancées comme les lookarounds et les quantificateurs
non-gourmands. Avec ces connaissances, vous êtes désormais prêt à résoudre des
problèmes réels et à intégrer les regex dans vos projets.
À mon avis, le plus important est de pratiquer et de garder vos regex simples et lisibles. Et n’oubliez pas : des outils comme Regex101 ↗ sont vos meilleurs amis pour tester et affiner vos expressions.
Maintenant, à vous de jouer ! 😊