> Guide complet des regex en Python avec le module re : match, search, findall, sub, classes de caractères, quantificateurs, groupes nommés, flags et exemples (email, dates).

*Source : https://coder-studio.com/tutoriels/regex-python/*

---

[// Python](https://coder-studio.com/tutoriels/)

# Les expressions régulières en Python (module re)

Par **Kévin Papot** · publié le 2 décembre 2025

Une **expression régulière** (ou _regex_) est un motif qui décrit un ensemble de chaînes de caractères. En Python, tout passe par le module `re` de la bibliothèque standard : il permet de rechercher, extraire, valider et remplacer du texte avec une précision chirurgicale. Ce guide couvre le sujet de façon exhaustive : les fonctions principales (`match`, `search`, `findall`, `sub`), la syntaxe des motifs (classes, quantificateurs, ancres, groupes), les groupes nommés, les flags, et des exemples concrets comme la validation d’emails et l’extraction de dates.

## Le module re et les chaînes brutes

On commence toujours par importer `re`. Les motifs s’écrivent dans des **chaînes brutes** (préfixe `r"..."`), qui empêchent Python d’interpréter les antislashs — essentiel car les regex en utilisent beaucoup.

```
import re

motif = r"\d+"   # r"" = chaîne brute, \d n'est pas échappé par Python
texte = "Il y a 42 chats et 7 chiens"

resultat = re.findall(motif, texte)
print(resultat)   # ['42', '7']
```

Sans le `r`, il faudrait écrire `"\\d+"`. Prenez l’habitude d’utiliser `r"..."` systématiquement pour vos motifs.

## re.search : trouver la première correspondance

`re.search(motif, texte)` parcourt toute la chaîne et renvoie un **objet Match** à la première correspondance, ou `None` si aucune.

```
import re

texte = "Commande n°A123 expédiée"
resultat = re.search(r"[A-Z]\d+", texte)

if resultat:
    print(resultat.group())   # A123
    print(resultat.start())   # 11 (position de départ)
```

L’objet Match est « vrai » dans un test `if`, ce qui rend la vérification très lisible.

## re.match : ancrer au début

`re.match` ne teste le motif qu’**au tout début** de la chaîne. Il renvoie `None` si la correspondance n’est pas en position zéro.

```
import re

print(re.match(r"\d+", "123 abc"))   # correspondance
print(re.match(r"\d+", "abc 123"))   # None (ne commence pas par un chiffre)
```

Retenez la différence : `match` = « commence par », `search` = « contient quelque part ».

## re.findall et re.finditer : toutes les correspondances

`re.findall` renvoie la **liste de toutes les correspondances**. `re.finditer` renvoie un itérateur d’objets Match, utile quand on a besoin des positions.

```
import re

texte = "prix : 12€, 8€ et 150€"

print(re.findall(r"\d+", texte))   # ['12', '8', '150']

for m in re.finditer(r"\d+", texte):
    print(m.group(), "à la position", m.start())
```

Attention : si le motif contient des groupes `(...)`, `findall` renvoie les groupes et non la correspondance complète — un piège fréquent que nous illustrons plus bas.

## re.sub : remplacer

`re.sub(motif, remplacement, texte)` remplace toutes les correspondances par la chaîne fournie.

```
import re

texte = "Contactez-nous au 06 12 34 56 78 svp"
masque = re.sub(r"\d", "X", texte)
print(masque)   # Contactez-nous au XX XX XX XX XX svp
```

Le remplacement peut aussi être une fonction, pour un traitement dynamique :

```
import re

def majuscule(m):
    return m.group().upper()

print(re.sub(r"\b\w", majuscule, "bonjour le monde"))   # Bonjour Le Monde
```

## La syntaxe des motifs : classes de caractères

Une classe de caractères décrit un ensemble de caractères acceptables.

### Les classes prédéfinies

-   `\d` : un chiffre (0-9)
-   `\w` : un caractère de mot (lettre, chiffre, underscore)
-   `\s` : un espace, une tabulation ou un retour à la ligne
-   `.` : n’importe quel caractère (sauf saut de ligne)

Leurs versions majuscules `\D`, `\W`, `\S` désignent l’inverse.

```
import re

print(re.findall(r"\w+", "hello_42 monde !"))   # ['hello_42', 'monde']
print(re.findall(r"\S+", "a b   c"))            # ['a', 'b', 'c']
```

### Les classes personnalisées avec \[ \]

Entre crochets, on définit son propre ensemble. Un tiret indique un intervalle, un `^` en tête signifie la négation.

```
import re

print(re.findall(r"[aeiou]", "programmation"))   # voyelles
print(re.findall(r"[A-Za-z]+", "Python 3.12"))   # ['Python']
print(re.findall(r"[^0-9]", "a1b2"))             # tout sauf des chiffres
```

## Les quantificateurs

Ils indiquent combien de fois l’élément précédent doit apparaître.

-   `*` : zéro fois ou plus
-   `+` : une fois ou plus
-   `?` : zéro ou une fois (optionnel)
-   `{n}` : exactement n fois
-   `{n,m}` : entre n et m fois

```
import re

print(re.findall(r"ab*", "a ab abb abbb"))   # ['a', 'ab', 'abb', 'abbb']
print(re.findall(r"\d{2,4}", "1 22 333 44444"))   # ['22', '333', '4444']
```

Par défaut les quantificateurs sont **gloutons** (ils prennent le maximum). Ajouter `?` les rend **paresseux** :

```
import re

print(re.findall(r"<.*>", "<a><b>"))    # ['<a><b>']  (glouton)
print(re.findall(r"<.*?>", "<a><b>"))   # ['<a>', '<b>']  (paresseux)
```

## Les ancres

Les ancres ne correspondent pas à des caractères mais à des **positions**.

-   `^` : début de chaîne (ou de ligne avec le flag MULTILINE)
-   `$` : fin de chaîne
-   `\b` : frontière de mot

```
import re

print(re.search(r"^Bonjour", "Bonjour tout le monde"))   # correspond
print(re.search(r"monde$", "Bonjour le monde"))          # correspond
print(re.findall(r"\bchat\b", "chat chaton chat"))       # ['chat', 'chat']
```

Le `\b` évite ici de capturer « chat » à l’intérieur de « chaton ».

## Les groupes de capture

Les parenthèses `(...)` créent un **groupe** dont on peut récupérer le contenu séparément avec `.group(n)`.

```
import re

texte = "2025-12-02"
m = re.search(r"(\d{4})-(\d{2})-(\d{2})", texte)

print(m.group(0))   # 2025-12-02  (correspondance complète)
print(m.group(1))   # 2025  (année)
print(m.group(2))   # 12    (mois)
print(m.groups())   # ('2025', '12', '02')
```

## Les groupes nommés

Pour un code plus lisible, on nomme les groupes avec `(?P<nom>...)` et on y accède par leur nom.

```
import re

texte = "2025-12-02"
m = re.search(r"(?P<annee>\d{4})-(?P<mois>\d{2})-(?P<jour>\d{2})", texte)

print(m.group("annee"))   # 2025
print(m.group("mois"))    # 12
print(m.groupdict())      # {'annee': '2025', 'mois': '12', 'jour': '02'}
```

C’est particulièrement précieux dans les motifs complexes où compter les parenthèses devient pénible.

## Les flags

Les flags modifient le comportement global du motif. On les passe en dernier argument.

-   `re.IGNORECASE` (ou `re.I`) : ignore la casse
-   `re.MULTILINE` (`re.M`) : `^` et `$` s’appliquent à chaque ligne
-   `re.DOTALL` (`re.S`) : `.` inclut aussi les sauts de ligne

```
import re

print(re.findall(r"python", "Python PYTHON python", re.IGNORECASE))
# ['Python', 'PYTHON', 'python']

texte = "ligne1\nligne2\nligne3"
print(re.findall(r"^ligne\d", texte, re.MULTILINE))
# ['ligne1', 'ligne2', 'ligne3']
```

## Compiler un motif avec re.compile

Si vous réutilisez un même motif de nombreuses fois, `re.compile` le pré-compile une seule fois et améliore la lisibilité.

```
import re

motif_tel = re.compile(r"\d{2} \d{2} \d{2} \d{2} \d{2}")

for ligne in ["06 12 34 56 78", "rien ici"]:
    if motif_tel.search(ligne):
        print("Numéro trouvé :", ligne)
```

## Exemple complet n°1 : valider un email

Un motif d’email pragmatique (aucune regex ne couvre parfaitement la norme, mais celle-ci suffit largement en pratique).

```
import re

motif_email = re.compile(r"^[\w.+-]+@[\w-]+\.[\w.-]+$")

for adresse in ["contact@coder-studio.com", "invalide@", "a.b@site.fr"]:
    if motif_email.match(adresse):
        print(adresse, "→ valide")
    else:
        print(adresse, "→ invalide")
```

## Exemple complet n°2 : extraire des dates

On extrait toutes les dates au format `JJ/MM/AAAA` d’un texte, avec des groupes nommés.

```
import re

texte = "Réunion le 02/12/2025, livraison le 15/01/2026."
motif = re.compile(r"(?P<jour>\d{2})/(?P<mois>\d{2})/(?P<annee>\d{4})")

for m in motif.finditer(texte):
    print(f"{m.group('jour')}-{m.group('mois')}-{m.group('annee')}")
```

Sortie :

```
02-12-2025
15-01-2026
```

## Conclusion

Le module `re` couvre tous les besoins de manipulation de texte par motif : `search` et `match` pour trouver, `findall` et `finditer` pour tout collecter, `sub` pour remplacer. Maîtrisez les classes de caractères, les quantificateurs et les groupes (nommés de préférence), et vous validerez emails, dates ou numéros de téléphone en quelques lignes. Pour des transformations plus simples, pensez aussi aux méthodes natives présentées dans notre guide sur [la manipulation de chaînes en Python](https://coder-studio.com/tutoriels/manipuler-chaines-python/).

## À lire ensuite

-   [Manipuler les chaînes de caractères en Python](https://coder-studio.com/tutoriels/manipuler-chaines-python/)
-   [Les fonctions en Python : tout ce qu’il faut savoir](https://coder-studio.com/tutoriels/fonctions-python/)
-   [Apprendre Python : par où commencer](https://coder-studio.com/tutoriels/apprendre-python/)
