
Une expression régulière (regex) est un motif qui décrit un ensemble de chaînes de caractères, pour rechercher, extraire ou remplacer du texte. En Python, tout passe par le module re, intégré à la bibliothèque standard : on écrit un motif comme r"\d+" (un ou plusieurs chiffres) et on l'applique à un texte. Ce guide part de zéro et couvre les bases (symboles, classes de caractères, quantificateurs), les fonctions du module re (search, match, findall, sub...), les groupes et lookarounds, puis les points de sécurité comme les attaques ReDoS.
Il s'adresse aux débutants qui découvrent les regex comme à celles et ceux qui veulent valider des formats ou extraire des données d'un texte. Chaque notion est illustrée par un exemple exécutable. Le code a été testé avec Python 3.12.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Lire et écrire un motif regex : symboles, classes de caractères, quantificateurs.
- Utiliser les fonctions du module
re:search,match,findall,sub,split. - Capturer des sous-parties avec les groupes, y compris nommés.
- Valider et affiner avec les lookarounds et
re.fullmatch. - Éviter les pièges de lisibilité et de sécurité (ReDoS).
Premier pas
Section intitulée « 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 reEt 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
Section intitulée « 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
Section intitulée « 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
Section intitulée « 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
Section intitulée « 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
Section intitulée « Classes de caractères prédéfinies »Ces classes simplifient les recherches courantes.
-
\dCorrespond à un chiffre (0-9). Exemple :import retexte = "Il y a 42 pommes"motif = r"\d+"resultat = re.search(motif, texte)print(resultat.group()) # "42" -
\DCorrespond à tout sauf un chiffre. Exemple :import retexte = "42 pommes"motif = r"\D+"resultat = re.search(motif, texte)print(resultat.group()) # " pommes" -
\wCorrespond à 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'] -
\WCorrespond à 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) # [' ', ' ', ' !'] -
\sCorrespond à 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) # [' ', ' '] -
\SCorrespond à 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
Section intitulée « 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
Section intitulée « 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}: exactementnoccurrences.{n,}: au moinsnoccurrences.{n,m}: entrenetmoccurrences.
Exemple :
import retexte = "aaaaa"motif = r"a{2,4}"resultat = re.search(motif, texte)print(resultat.group()) # "aaaa"
Quantificateurs "gourmands" et "non-gourmands"
Section intitulée « 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
Section intitulée « 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
Section intitulée « 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()
Section intitulée « 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()
Section intitulée « 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.fullmatch()
Section intitulée « Fonction re.fullmatch() »Pour valider un format, re.match et re.search ne suffisent pas : ils
acceptent une correspondance partielle. La fonction re.fullmatch() exige
que le motif couvre toute la chaîne, du premier au dernier caractère.
import re
bool(re.fullmatch(r"\d{5}", "75001")) # Truebool(re.fullmatch(r"\d{5}", "75001x")) # False, un caractère en tropC'est la bonne fonction pour vérifier un code postal, un identifiant ou
tout format attendu. Avec re.search, "75001x" correspondrait quand même.
Fonction re.findall()
Section intitulée « 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()
Section intitulée « 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()
Section intitulée « 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 puissantFonction re.split()
Section intitulée « 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()
Section intitulée « 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
Section intitulée « 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 ?
Section intitulée « 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 groupeSortie :
Match complet : 06-12-34-56-78Groupe 1 : 06Groupe 2 : 12Numérotation des groupes
Section intitulée « 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)) # 01Nommage des groupes
Section intitulée « 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")) # 01Récupérer tous les groupes
Section intitulée « 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
Section intitulée « 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
Section intitulée « 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)) # 06Groupes alternatifs
Section intitulée « 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 orangesUtilisation pratique
Section intitulée « 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
Section intitulée « 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
Section intitulée « 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
Section intitulée « 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
Section intitulée « 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"
Sécurité : attention aux attaques ReDoS
Section intitulée « Sécurité : attention aux attaques ReDoS »Une regex n'est pas seulement une question de lisibilité, c'est aussi un risque de sécurité. Un motif mal formé peut provoquer un backtracking catastrophique : sur une entrée piégée, le moteur explore un nombre exponentiel de combinaisons et le programme se bloque pendant des secondes, voire des minutes. C'est une attaque par déni de service appelée ReDoS (Regular expression Denial of Service).
import re
# DANGEREUX sur une entrée non fiable : ce motif peut bloquer le programmere.match(r"(a+)+$", "a" * 40 + "!")Le motif (a+)+ imbrique deux quantificateurs, ce qui multiplie les chemins à
explorer quand le texte ne correspond pas. Sur une chaîne fournie par un
utilisateur, c'est une porte ouverte au blocage.
Trois réflexes pour s'en prémunir :
- Simplifier le motif et éviter les quantificateurs imbriqués (
(a+)+,(.*)*). - Sur une entrée non fiable, préférer les quantificateurs possessifs
(
a++,\d++) ou les groupes atomiques ((?>...)), ajoutés au modulereen Python 3.11. Ils interdisent le retour en arrière et coupent court au backtracking.
import re
# Possessif et groupe atomique : pas de backtracking, donc pas de ReDoSre.match(r"a++b", "aaab") # aaabre.match(r"(?>a+)b", "aaab") # aaabBonnes pratiques
Section intitulée « Bonnes pratiques »Les expressions régulières sont puissantes, mais elles peuvent vite devenir un casse-tête si on les utilise mal. Voici quelques bonnes pratiques pour écrire des regex efficaces et 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
Section intitulée « Astuces pour le débogage »-
Utilisez
re.DEBUGpour 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.
À retenir
Section intitulée « À retenir »- Les expressions régulières Python passent par le module
re:search,match,findall,subcouvrent 95 % des cas. - Les groupes nommés (
(?P<nom>...)) etgroupdict()donnent du sens aux captures et évitent les indices fragiles. - Les lookarounds (
(?=...),(?!...)) permettent de matcher sans consommer, utile pour valider sans extraire. - Le quantificateur non-gourmand (
*?,+?) évite les matches trop larges sur du HTML/JSON imbriqué. - Le piège principal reste la lisibilité : une regex simple +
commentée bat toujours une regex compacte non-relisable. Le mode
re.VERBOSEformate la regex sur plusieurs lignes. - Regex101 reste l'outil de référence pour prototyper, expliquer chaque token et exporter le résultat.
- Sur une entrée non fiable, méfiez-vous des ReDoS : motif simple, et
quantificateurs possessifs (
a++) si besoin (Python 3.11+).
FAQ : les expressions régulières en Python
Section intitulée « FAQ : les expressions régulières en Python »re est intégré à Python, aucune installation :import re
texte = "Il y a 42 pommes"
resultat = re.search(r"\d+", texte)
if resultat:
print(resultat.group()) # 42
- On écrit le motif dans une chaîne brute préfixée par
r(r"\d+") pour éviter les problèmes d'antislash. re.searchrenvoie un objet match, ouNonesi rien ne correspond..group()récupère le texte trouvé.
re.match(r"Python", "J'aime Python") # None (pas au début)
re.search(r"Python", "J'aime Python") # trouve Python
re.matchne teste qu'au tout début de la chaîne.re.searchcherche n'importe où.
re.search. Pour vérifier que toute la chaîne correspond (validation), utilisez re.fullmatch.import re
texte = "123 456 789"
re.findall(r"\d+", texte) # ['123', '456', '789']
for m in re.finditer(r"\d+", texte):
print(m.group(), m.start()) # valeur + position
re.findallrenvoie la liste des correspondances (les valeurs).re.finditerrenvoie un itérateur d'objets match, avec la position (.start(),.end()).
re.sub(motif, remplacement, texte) remplace toutes les occurrences :import re
re.sub(r"Python", "Java", "Python est génial")
# 'Java est génial'
Le remplacement peut réutiliser les groupes capturés :re.sub(r"(\d{4})-(\d{2})", r"\2/\1", "2026-07") # '07/2026'
On peut même passer une fonction comme remplacement pour un traitement dynamique de chaque correspondance.re.fullmatch n'accepte que si le motif couvre toute la chaîne :import re
bool(re.fullmatch(r"\d{5}", "75001")) # True
bool(re.fullmatch(r"\d{5}", "75001x")) # False
C'est la fonction idéale pour valider un code postal, un identifiant ou un format attendu. Avec re.search, la chaîne 75001x correspondrait quand même (match partiel) ; fullmatch l'exige entière.import re
# DANGEREUX sur entrée non fiable : peut bloquer des secondes/minutes
re.match(r"(a+)+$", "a" * 40 + "!")
Pour l'éviter :- Simplifiez les motifs, évitez les quantificateurs imbriqués (
(a+)+). - Sur une entrée non fiable, utilisez les quantificateurs possessifs (
a++) ou groupes atomiques ((?>a+)), ajoutés en Python 3.11, qui empêchent le backtracking.
Prochaines étapes
Section intitulée « Prochaines étapes »Les regex servent surtout à extraire, valider et nettoyer du texte. Voici les sujets qui s'y rattachent directement.