Introduction : Les regex, un super-pouvoir pour le texte
Tu as déjà dû vérifier si une adresse email était bien formée, extraire un numéro de téléphone d'un texte ou remplacer des mots précis dans un document. Faire ça "à la main" avec des boucles et des conditions, c'est long et compliqué. Heureusement, il existe un outil puissant : les expressions régulières, souvent appelées regex ou regexp. En Python, grâce au module re, tu peux maîtriser cet outil et gagner un temps fou dans tes projets NSI. Ce guide va t'apprendre les bases et te montrer comment les utiliser en pratique.
Les bases du module re en Python
Pour utiliser les expressions régulières en Python, il faut importer le module re. C'est un module de la bibliothèque standard, donc pas besoin d'installation supplémentaire. Les regex sont des modèles de recherche écrits dans un langage spécial. On les utilise principalement pour trois opérations :
- Rechercher (
re.search()) : Vérifier si un motif est présent quelque part dans une chaîne. - Faire correspondre (
re.match()) : Vérifier si un motif correspond au début d'une chaîne. - Trouver toutes les occurrences (
re.findall()) : Extraire toutes les sous-chaînes qui correspondent au motif.
Voici un exemple simple pour démarrer :
import re
texte = "Mon numéro est le 06-12-34-56-78."
pattern = r"\d{2}-\d{2}-\d{2}-\d{2}-\d{2}"
resultat = re.search(pattern, texte)
if resultat:
print("Numéro trouvé :", resultat.group())Ici, le motif \d{2} cherche deux chiffres consécutifs. Le r devant la chaîne du motif indique une raw string, ce qui simplifie l'écriture des antislashs (\).
Construire son motif : les métacaractères essentiels
La puissance des regex vient des métacaractères, des symboles qui ont une signification spéciale. Voici les plus importants à connaître :
- . (point) : Correspond à n'importe quel caractère (sauf un saut de ligne).
- \d : Correspond à un chiffre (équivalent à
[0-9]). - \w : Correspond à un caractère alphanumérique (lettre, chiffre ou underscore).
- \s : Correspond à un espace blanc (espace, tabulation, retour à la ligne).
- [abc] : Correspond à un seul caractère parmi ceux listés (a, b ou c).
- [^abc] : Correspond à un caractère qui n'est PAS a, b ou c.
- ^ : Début de la chaîne (quand il n'est pas dans des crochets).
- $ : Fin de la chaîne.
Les quantificateurs : combien de fois ?
Pour spécifier le nombre de répétitions d'un caractère ou d'un groupe, on utilise des quantificateurs :
- * : 0 fois ou plus.
- + : 1 fois ou plus.
- ? : 0 fois ou 1 fois (caractère optionnel).
- {n} : Exactement n fois.
- {n, m} : Entre n et m fois.
Exemple : Le motif r"\w+\.?\w*@\w+\.\w{2,3}" est une première approche (très simplifiée) pour chercher une adresse email.
Cas pratiques pour tes projets NSI
Voyons maintenant comment appliquer ces connaissances à des problèmes concrets que tu pourrais rencontrer.
1. Valider un format de données
Imaginons que tu doives vérifier qu'un utilisateur a bien saisi une date au format JJ/MM/AAAA.
def valider_date(date_str):
pattern = r"^(0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[0-2])/\d{4}$"
return re.match(pattern, date_str) is not None
print(valider_date("25/12/2023")) # True
print(valider_date("31/02/2023")) # True (le motif ne vérifie pas la validité du jour pour le mois)
print(valider_date("1/1/23")) # FalseCe motif décompose : (0[1-9]|[12][0-9]|3[01]) pour le jour (01-09, 10-29, ou 30-31), puis le séparateur /, puis le mois, puis l'année à 4 chiffres. Les ancres ^ et $ assurent que toute la chaîne correspond.
2. Extraire des informations d'un texte
Tu as un texte et tu veux en extraire tous les hashtags (mots commençant par #).
texte = "Super projet #NSI ! J'adore le #Python. #coding #2024"
hashtags = re.findall(r"#\w+", texte)
print(hashtags) # ['#NSI', '#Python', '#coding', '#2024']La fonction findall() est parfaite pour ce genre de tâche d'extraction.
3. Remplacer ou diviser du texte
Tu peux aussi utiliser re.sub() pour remplacer et re.split() pour diviser.
# Remplacer plusieurs espaces par un seul
texte_sale = "Voici un texte avec trop d'espaces."
texte_propre = re.sub(r"\s+", " ", texte_sale)
print(texte_propre)
# Diviser selon plusieurs séparateurs possibles
donnees = "Pommes; Bananes, Cerises et Poires"
fruits = re.split(r"[;,\s] et ", donnees)
print(fruits) # ['Pommes; Bananes, Cerises', 'Poires']Aller plus loin : groupes capturants et flags
Pour extraire des parties spécifiques d'une correspondance, utilise les parenthèses pour créer des groupes capturants.
texte = "Contacte-moi au 06-12-34-56-78 ou au 01-23-45-67-89."
pattern = r"(\d{2})-(\d{2}-\d{2}-\d{2}-\d{2})"
for match in re.finditer(pattern, texte):
print("Indicatif:", match.group(1), "- Numéro:", match.group(2))Les flags modifient le comportement de la recherche. Le plus utile est re.IGNORECASE (ou re.I) pour une recherche insensible à la casse.
re.search(r"python", "J'aime Python", re.IGNORECASE).group() # Retourne 'Python'Conclusion et bonnes pratiques
Les expressions régulières sont un outil incroyablement puissant, mais elles peuvent vite devenir complexes ("regex hell"). Suis ces conseils :
- Commence simple : Teste ton motif petit à petit.
- Utilise des raw strings (
r"...") pour éviter les problèmes d'échappement. - Commente tes motifs complexes avec
re.VERBOSE. - Ne réinvente pas la roue : Pour valider un email ou une URL, cherche d'abord une regex éprouvée en ligne.
- Teste en ligne : Des sites comme regex101.com te permettent de visualiser et de déboguer tes motifs interactivement.
Avec de la pratique, tu verras que les regex deviendront un réflexe pour nettoyer des données, parser des logs ou valider des formulaires dans tes projets Python. Bonne exploration !
