1. À propos du module re et des bases des expressions régulières
Le module re (regular expressions) de Python fournit toutes les fonctionnalités nécessaires pour manipuler du texte à l'aide d'expressions régulières. Une expression régulière est une séquence de caractères qui définit un motif de recherche. Elle permet de valider, extraire ou remplacer des chaînes de caractères de manière puissante et concise.
Les métacaractères fondamentaux sont : . (n'importe quel caractère saut ligne), ^ (début de chaîne), $ (fin de chaîne), * (0 ou plus), + (1 ou plus), ? (0 ou 1), {n,m} (entre n et m fois), [] (classe de caractères), | (ou), () (groupe de capture).
2. Fonctions principales de recherche : match, search et findall
Les trois fonctions les plus utilisées pour rechercher des motifs sont re.match() (cherche uniquement au début), re.search() (cherche partout dans la chaîne) et re.findall() (retourne toutes les occurrences).
2.1 re.match() : Vérifier le début d'une chaîne
re.match() vérifie si le motif correspond au début de la chaîne. Si c'est le cas, elle retourne un objet Match, sinon None.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import re # Exemple : vérifier si la chaîne commence par "Python" chaine = "Python est puissant" resultat = re.match(r"Python", chaine) if resultat: print("Correspondance trouvée au début") print(f"Texte trouvé : {resultat.group()}") else: print("Aucune correspondance") # Test avec une chaîne ne commençant pas par le motif chaine2 = "J'aime Python" resultat2 = re.match(r"Python", chaine2) print(resultat2) # None # Sortie : # Correspondance trouvée au début # Texte trouvé : Python # None |
2.2 re.search() : Rechercher un motif n'importe où
re.search() parcourt toute la chaîne et s'arrête à la première occurrence du motif. Elle est plus flexible que match().
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import re texte = "Le code Python 3.10 est sorti en 2021" # Recherche d'un numéro de version (chiffres point chiffres) motif = r"\d+\.\d+" resultat = re.search(motif, texte) if resultat: print(f"Version trouvée : {resultat.group()}") print(f"Position : de {resultat.start()} à {resultat.end()}") else: print("Non trouvé") # Sortie : # Version trouvée : 3.10 # Position : de 13 à 17 |
2.3 re.findall() : Extraire toutes les occurrences
re.findall() retourne une liste de toutes les sous-chaînes correspondant au motif. Idéal pour extraire toutes les occurrences d'un motif dans un texte.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import re texte = "Emails : jean@email.com, marie@work.net, admin@site.org" # Motif simple pour trouver des adresses email motif = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" emails = re.findall(motif, texte) print(f"Emails trouvés : {emails}") print(f"Nombre d'emails : {len(emails)}") # Sortie : # Emails trouvés : ['jean@email.com', 'marie@work.net', 'admin@site.org'] # Nombre d'emails : 3 |
3. Substitution et découpage : sub et split
Les fonctions re.sub() et re.split() permettent respectivement de remplacer des motifs et de découper des chaînes de manière avancée.
3.1 re.sub() : Remplacer du texte par motif
re.sub() remplace toutes les occurrences d'un motif par une chaîne de remplacement. On peut aussi utiliser une fonction de remplacement pour un contrôle précis.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import re texte = "Le prix est de 100 euros, et 200 dollars, puis 50 livres" # Remplacer tous les nombres par [NOMBRE] texte_modifie = re.sub(r"\d+", "[NOMBRE]", texte) print(texte_modifie) # Remplacement avec fonction : doubler la valeur des nombres def double(match): valeur = int(match.group()) return str(valeur * 2) texte_double = re.sub(r"\d+", double, texte) print(texte_double) # Sortie : # Le prix est de [NOMBRE] euros, et [NOMBRE] dollars, puis [NOMBRE] livres # Le prix est de 200 euros, et 400 dollars, puis 100 livres |
3.2 re.split() : Découpage avancé avec motifs
re.split() découpe une chaîne selon un motif. Plus puissant que str.split() car il peut utiliser des séparateurs complexes.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import re # Découper sur plusieurs types de séparateurs : espaces, virgules, points texte = "Python, Java; C++.JavaScript:Ruby" # Motif : un ou plusieurs espaces, virgules, points-virgules, deux-points mots = re.split(r"[ ,;:.]+", texte) print(mots) # Garder les séparateurs avec des groupes de capture (option) avec_sep = re.split(r"([ ,;:.]+)", texte) print(avec_sep) # Sortie : # ['Python', 'Java', 'C', 'JavaScript', 'Ruby'] # ['Python', ', ', 'Java', '; ', 'C', '++.', 'JavaScript', ':', 'Ruby'] |
4. Compilation et optimisation avec re.compile()
Lorsqu'un même motif est utilisé plusieurs fois, il est recommandé de le compiler avec re.compile(). Cela améliore les performances et rend le code plus lisible en factorisant le motif.
4.1 Compilation d'un motif réutilisable
La méthode compile() retourne un objet Pattern qui possède les mêmes méthodes (search(), findall(), etc.) que le module re.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import re # Compilation d'un motif pour une adresse IPv4 motif_ip = re.compile(r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b") # Réutilisation multiple texte1 = "Serveur 192.168.1.1 et routeur 10.0.0.1" texte2 = "Adresse invalide 999.999.999.999 et valide 172.16.0.1" ips1 = motif_ip.findall(texte1) ips2 = motif_ip.findall(texte2) print(f"IPs dans texte1 : {ips1}") print(f"IPs dans texte2 : {ips2}") # Vérification de validité (simple) for ip in motif_ip.findall(texte2): parties = ip.split('.') valide = all(0 <= int(p) <= 255 for p in parties) print(f"{ip} est {'valide' if valide else 'invalide'}") # Sortie : # IPs dans texte1 : ['192.168.1.1', '10.0.0.1'] # IPs dans texte2 : ['999.999.999.999', '172.16.0.1'] # 999.999.999.999 est invalide # 172.16.0.1 est valide |
5. Groupes de capture, lookahead et cas avancés
Les groupes de capture permettent d'extraire des parties spécifiques d'un motif. Les assertions lookahead ((?=...)) et lookbehind ((?<=...)) permettent de créer des conditions sans consommer de caractères.
5.1 Utilisation des groupes nommés et non nommés
Les groupes de capture (entre parenthèses) permettent d'extraire des sous-parties. Avec groupdict() pour les groupes nommés, on obtient un dictionnaire structuré.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import re # Extraction de données structurées : nom, prénom, âge texte = "Durand, Jean, 32 ans ; Martin, Sophie, 28 ans" # Groupes nommés : (?P<nom>...) motif = re.compile(r"(?P<nom>[A-Za-z]+),\s*(?P<prenom>[A-Za-z]+),\s*(?P<age>\d+)\s*ans") for match in motif.finditer(texte): print(f"--- Personne ---") print(f"Nom : {match.group('nom')}") print(f"Prénom : {match.group('prenom')}") print(f"Âge : {match.group('age')}") # Alternative : obtenir tout le dictionnaire print(f"Dictionnaire : {match.groupdict()}") # Sortie : # --- Personne --- # Nom : Durand # Prénom : Jean # Âge : 32 # Dictionnaire : {'nom': 'Durand', 'prenom': 'Jean', 'age': '32'} # --- Personne --- # Nom : Martin # Prénom : Sophie # Âge : 28 # Dictionnaire : {'nom': 'Martin', 'prenom': 'Sophie', 'age': '28'} |
5.2 Assertions lookahead et lookbehind
Les assertions permettent de vérifier une condition sans inclure la condition dans le résultat. (?=...) pour lookahead positif, (?<=...) pour lookbehind positif.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import re # Extraire tous les nombres suivis de "euros" (sans capturer "euros") texte = "Prix: 100 euros, 50 dollars, 75 euros, 30 livres" # Lookahead positif : trouver les nombres suivis de " euros" nombres_euros = re.findall(r"\d+(?=\s+euros)", texte) print(f"Nombres en euros : {nombres_euros}") # Extraire les mots précédés de "Prix: " (lookbehind) mots_prix = re.findall(r"(?<=Prix: )\d+", texte) print(f"Prix extrait : {mots_prix}") # Exemple plus complexe : trouver des adresses IP suivies de ":8080" log = "192.168.1.1:8080, 10.0.0.2:80, 172.16.0.1:8080" ips_8080 = re.findall(r"\b(?:\d{1,3}\.){3}\d{1,3}(?=:8080)", log) print(f"IPs sur port 8080 : {ips_8080}") # Sortie : # Nombres en euros : ['100', '75'] # Prix extrait : ['100'] # IPs sur port 8080 : ['192.168.1.1', '172.16.0.1'] |
5.3 Gestion des drapeaux (flags) : ignorecase, multiline, verbose
Les drapeaux modifient le comportement de l'expression régulière. Les plus courants sont re.IGNORECASE (insensible à la casse), re.MULTILINE (^ et $ agissent sur chaque ligne) et re.VERBOSE (permet d'écrire des motifs commentés et espacés).
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import re # 1. IGNORECASE : ignorer la casse texte = "Python, PYTHON, python" motif = re.compile(r"python", re.IGNORECASE) print(motif.findall(texte)) # Toutes les variations # 2. VERBOSE : motif commenté et lisible motif_verbose = re.compile(r""" \b # début de mot [A-Za-z0-9._%+-]+ # nom local @ # arobase [A-Za-z0-9.-]+ # nom de domaine \. # point [A-Za-z]{2,} # extension \b # fin de mot """, re.VERBOSE | re.IGNORECASE) emails = motif_verbose.findall("Contact: Jean@Example.COM ou marie@work.net") print(f"Emails trouvés : {emails}") # Sortie : # ['Python', 'PYTHON', 'python'] # Emails trouvés : ['Jean@Example.COM', 'marie@work.net'] |
Auteur : Younes Derfoufi
Lieu de travail : CRMEF OUJDA
Site Web : www.tresfacile.net
Chaine YouTube : https://www.youtube.com/user/InformatiquesFacile
Me contacter : https://www.tresfacile.net/me-contacter/



