Maîtriser les Expressions Régulières en Python : Extraction, Substitution et Nettoyage de Textes

Fondamentaux de l'Identification de Motifs

Le module intégré re offre une interface robuste pour scanner et analyser des chaînes de caractères complexes. Deux approches complémentaires permettent de localiser des correspondances : le parcours intégral via re.search() qui s'arrête au premier résultat trouvé, et la validation exclusive du début de chaîne avec re.match().

import re

facture_brut = "Référence fac:INV-987X,Montant:1250.50€,Client:Dupont"
pat_prix = r"Montant\s*:\s*([\d,.]+)\€"

match_mnt = re.search(pat_prix, facture_brut)
if match_mnt:
    print(f"Valeur monétaire : {match_mnt.group(1)}")  # Sortie : 1250.50

ref_tete = re.match(r"Référence fac\s*:\s*(\w+)", facture_brut)
print(ref_tete.group(1))  # Sortie : INV-987X

Lorsque plusieurs occurences doivent être collectées simultanément, re.findall() retourne une liste native contenant chaque élément satisfaisant le critère de sélection.

changelog = "Build v1.4.2 actif, montée de version vers v1.5.0 planifiée, correctif v1.4.3 publié"
versions_identifiees = re.findall(r"\bv[\d]+\.[\d]+\.[\d]+\b", changelog)
print(versions_identifiees)  # Sortie : ['v1.4.2', 'v1.5.0', 'v1.4.3']

Transformation et Remplacement Dynamique

La fonction re.sub() remplace les fragments correspondant au motif par une nouvelle séquence. Elle accepte soit une chaîne littérale, soit une callable dont le retour définit la valeur injectée.

# Anonymisation partielle d'un numéro de sécurité sociale
donnee_personnelle = "NIS complet : 10813830112045"
donnee_masquee = re.sub(r"(\d{3})\d{4}(\d{4})", r"\1-xx-\2", donnee_personnelle)
print(donnee_masquee)  # Sortie : NIS complet : 108-xx-112

Les conversions algorithmiques profitent pleinement du passage d'une fonction gestionnaire :

rapport_capteurs = "Zone Est : 20℃ Zone Ouest : 35℃"

def converter_cversf(objet_match):
    degres_c = float(objet_match.group(1))
    return f"{degres_c * 1.8 + 32:.1f}°F"

rapport_converti = re.sub(r"(-?\d+\.?\d*)℃", converter_cversf, rapport_capteurs)
print(rapport_converti)  # Sortie : Zone Est : 68.0°F Zone Ouest : 95.0°F

Le réagencement structural de dates illustre cette modularité :

journal_systeme = "Archivage : 2024-03-15 Sauvegarde : 2024-04-01"
format_europeen = re.sub(r"(\d{4})-(\d{2})-(\d{2})", r"\3/\2/\1", journal_systeme)
print(format_europeen)  # Sortie : Archivage : 15/03/2024 Sauvegarde : 01/04/2024

Capture Structurée et Groupement

Encadrer une portion du motif entre parenthèses crée un groupe accessible indexé. Cela évite les scans multiples et accélère l'extraction ciblie.

contact_technique = "Support : (01) 9876-5432"
reg_groupes = r"\((\d{2})\)\s*(\d+-\d+)"

resultat = re.search(reg_groupes, contact_technique)
if resultat:
    print(f"Indicatif : {resultat.group(1)} | Numéro : {resultat.group(2)}")
    # Sortie : Indicatif : 01 | Numéro : 9876-5432

Pour renforcer la maintenabilité, les regroupements nommés ((?P<nom>...)</nom>) retournent un dictionnaire interprétable sans référence positionnelel.

evenau_reseau = "Nœud Alpha-IP établi liaison avec route_Beta"
schema_noms = r"(?P<srv>\w+)-IP.*liaison_(?P<rt>\w+)"
reponse_dico = re.search(schema_noms, evenau_reseau)
if reponse_dico:
    print(reponse_dico.groupdict())  
    # Sortie : {'srv': 'Alpha', 'rt': 'Beta'}</rt></srv>

L'itération contrôlée via re.finditer() restitue des objets Match complets, préservant les bornes .start() et .end() pour le traitement postérieur.

depot_sources = "Archive ftp://mirror.net/pkg.tar et dépôt https://cdn.dev/lib.so"
regexp_url = re.compile(r"https?://\S+")

for pos in regexp_url.finditer(depot_sources):
    print(f"Ressource localisée [{pos.start():4}-{pos.end():4}] : {pos.group()}")
    # Affiche chaque URI avec ses coordonnées exactes

Fiabilisation et Optimisation Mémoire

Toujours tester l'existence de l'objet returned avant tout appel à .group() pour bloquer les AttributeError inhérents aux recherches infructueuses.

bloc_vide = "Configuration initiale"
verification_numerique = re.search(r"\d+", bloc_vide)
if verification_numerique:
    print(verification_numerique.group())
else:
    print("Aucune donnée chiffrée détectée")

La compilation anticipée avec re.compile() amortit drastiquement la surcharge d'analyse lors de l'applicaton répétée du même schéma.

validateur_ip = re.compile(r"\b(?:\d{1,3}\.){3}\d{1,3}\b")
trafic_journalier = [
    "Handshake OK : 10.0.0.5",
    "Déclenchement alerte : 192.168.0.99",
    "Statut opérationnel"
]

for entrée in trafic_journalier:
    if validateur_ip.search(entrée):
        print(f"Nœud réseau confirmé dans : {entrée}")

Schémas Opérationnels Fréquents

Déparasitage de balises résiduelles :

fragment_html = "<aside>Note critique<main>Contenu principal<footer>Pied page</footer></main></aside>"
texte_nu = re.sub(r"<[^>]+>", "", fragment_html)
print(texte_nu)  # Sortie : Note critiqueContenu principalPied page

Prélèvement d'identifiants réseau :

entrée_audit = "Trace 77: Origine 172.16.0.12 politique ACCEPT"
adresse_extraite = re.search(r"\b(?:\d{1,3}\.){3}\d{1,3}\b", entrée_audit).group()
print(adresse_extraite)  # Sortie : 172.16.0.12

Contrôle de conformité syntaxique :

def authentifier_profil(id_utilisateur: str) -> bool:
    règle_alphanum = r"^[a-z][a-z0-9_]{2,19}$"
    return re.fullmatch(règle_alphanum, id_utilisateur) is not None

print(authentifier_profil("admin_usr"))  # True
print(authentifier_profil("9bad_acc"))   # False

Étiquettes: Python regex module-re extraction-textuelle manipulation-chaines

Publié le 8 octobre à 16h45