Python - Expressions Régulières
Bonjour à tous, futurs sorciers Python ! Aujourd'hui, nous allons entreprendre un voyage passionnant dans le monde des expressions régulières (regex) en Python. Ne vous inquiétez pas si vous n'avez jamais entendu parler de regex avant - à la fin de ce tutoriel, vous manipulerez cette puissante arme comme un pro !
Qu'est-ce qu'une Expression Régulière ?
Avant de plonger dans les détails, voyons ce qu'ont sont les expressions régulières. Imaginez-vous en tant que détective cherchant un motif spécifique dans un océan de texte. Les expressions régulières sont votre loupe, vous aidant à rechercher et à manipuler des chaînes de caractères en fonction de motifs. C'est assez cool, non ?
Chaînes Brutes
En Python, lorsque vous travaillez avec des regex, vous utilisez souvent des chaînes brutes. Celles-ci sont préfixées par un 'r' et traitent les barres obliques inverses comme des caractères littéraux. C'est particulièrement utile dans les regex car les barres obliques inverses sont courantes.
# Chaîne normale
print("Bonjour\nMonde")
# Chaîne brute
print(r"Bonjour\nMonde")
Dans le premier cas, vous verrez "Bonjour" et "Monde" sur des lignes séparées. Dans le second, vous verrez "Bonjour\nMonde" tel quel. Cela devient crucial lorsque vous travaillez avec des motifs regex.
Méta-caractères
Les méta-caractères sont les briques de base des regex. Ils ont des significations spéciales et nous aident à définir des motifs. Voici quelques-uns des plus courants :
Méta-caractère | Signification |
---|---|
. | Correspond à n'importe quel caractère sauf le saut de ligne |
^ | Correspond au début d'une chaîne |
$ | Correspond à la fin d'une chaîne |
* | Correspond à 0 ou plusieurs répétitions |
+ | Correspond à 1 ou plusieurs répétitions |
? | Correspond à 0 ou 1 répétition |
{} | Correspond à un nombre de répétitions spécifié explicitement |
[] | Spécifie un ensemble de caractères à correspondre |
\ | Échappe les caractères spéciaux |
La Fonction re.match()
La fonction re.match()
tente de faire correspondre un motif au début d'une chaîne. Si elle trouve une correspondance, elle renvoie un objet de correspondance ; sinon, elle renvoie None.
import re
résultat = re.match(r"Bonjour", "Bonjour, Monde !")
if résultat:
print("Correspondance trouvée :", résultat.group())
else:
print("Aucune correspondance")
Cela imprime "Correspondance trouvée : Bonjour". La méthode group()
renvoie la sous-chaîne correspondante.
La Fonction re.search()
Alors que re.match()
recherche une correspondance au début de la chaîne, re.search()
scanne toute la chaîne pour trouver une correspondance.
import re
résultat = re.search(r"Monde", "Bonjour, Monde !")
if résultat:
print("Correspondance trouvée :", résultat.group())
else:
print("Aucune correspondance")
Cela imprime "Correspondance trouvée : Monde".
Correspondance vs Recherche
La différence principale entre match()
et search()
est que match()
vérifie la correspondance uniquement au début de la chaîne, tandis que search()
vérifie la correspondance n'importe où dans la chaîne.
La Fonction re.findall()
La fonction re.findall()
renvoie toutes les correspondances non chevauchantes d'un motif dans une chaîne sous forme de liste.
import re
texte = "La pluie en Espagne tombe principalement dans la plaine"
résultat = re.findall(r"ain", texte)
print(résultat)
Cela imprime ['ain', 'ain', 'ain']
.
La Fonction re.sub()
La fonction re.sub()
remplace toutes les occurrences d'un motif dans une chaîne par une chaîne de remplacement.
import re
texte = "La pluie en Espagne"
résultat = re.sub(r"a", "o", texte)
print(résultat)
Cela imprime "La pluie en Spoine".
La Fonction re.compile()
La fonction re.compile()
crée un objet regex pour réutilisation, ce qui peut être plus efficace si vous utilisez le même motif plusieurs fois.
import re
motif = re.compile(r"\d+")
résultat1 = motif.findall("Il y a 123 pommes et 456 oranges")
résultat2 = motif.findall("J'ai 789 bananes")
print(résultat1)
print(résultat2)
Cela imprime ['123', '456']
et ['789']
.
La Fonction re.finditer()
La fonction re.finditer()
renvoie un itérateur produisant des objets de correspondance pour toutes les correspondances non chevauchantes d'un motif dans une chaîne.
import re
texte = "La pluie en Espagne"
for correspondance in re.finditer(r"ain", texte):
print(f"Trouvé '{correspondance.group()}' à la position {correspondance.start()}-{correspondance.end()}")
Cela imprime :
Trouvé 'ain' à la position 5-8
Trouvé 'ain' à la position 17-20
Cas d'Utilisation des Expressions Régulières en Python
Les expressions régulières ont de nombreuses applications pratiques. Examinons un cas d'utilisation courant :
Trouver des mots commençant par des voyelles
import re
texte = "Un pomme par jour garde le médecin loin"
mots_voyelles = re.findall(r'\b[aeiouAEIOU]\w+', texte)
print(mots_voyelles)
Cela imprime ['Un', 'pomme', 'a', 'loin']
.
Modificateurs d'Expression Régulière : Options d'Indicateurs
Le module re de Python fournit plusieurs indicateurs d'option qui modifient la manière dont les motifs sont interprétés :
Indicateur | Description |
---|---|
re.IGNORECASE (re.I) | Effectue une correspondance insensible à la casse |
re.MULTILINE (re.M) | Fait correspondre ^ au début de chaque ligne et $ à la fin de chaque ligne |
re.DOTALL (re.S) | Fait correspondre . à n'importe quel caractère, y compris le saut de ligne |
re.VERBOSE (re.X) | Vous permet d'écrire des motifs regex plus lisibles |
Motifs d'Expressions Régulières
Explorons quelques motifs plus avancés :
Classes de Caractères
Les classes de caractères vous permettent de spécifier un ensemble de caractères à faire correspondre :
import re
texte = "Le rapide布朗 fox saute par-dessus le chien paresseux"
résultat = re.findall(r"[aeiou]", texte)
print(résultat)
Cela imprime toutes les voyelles trouvées dans le texte.
Classes de Caractères Spéciaux
Python regex prend en charge les classes de caractères spéciaux :
Classe | Description |
---|---|
\d | Correspond à n'importe quel chiffre décimal |
\D | Correspond à n'importe quel caractère non numérique |
\s | Correspond à n'importe quel caractère d'espacement |
\S | Correspond à n'importe quel caractère non d'espacement |
\w | Correspond à n'importe quel caractère alphanumérique |
\W | Correspond à n'importe quel caractère non alphanumérique |
Cas de Répétition
Nous pouvons spécifier combien de fois un motif doit apparaître :
import re
texte = "J'ai 111 pommes et 22 oranges"
résultat = re.findall(r"\d{2,3}", texte)
print(résultat)
Cela imprime ['111', '22']
, correspondant aux nombres avec 2 ou 3 chiffres.
Répétition Non Gourmande
Par défaut, la répétition est gourmande, ce qui signifie qu'elle correspond au plus possible. Ajouter un ? après la répétition la rend non gourmande :
import re
texte = "<h1>Titre</h1><p>Paragraphe</p>"
gourmand = re.findall(r"<.*>", texte)
non_gourmand = re.findall(r"<.*?>", texte)
print("Gourmand :", gourmand)
print("Non gourmand :", non_gourmand)
Cela montrera la différence entre les correspondances gourmandes et non gourmandes.
Groupement avec Parenthèses
Les parenthèses permettent de regrouper des parties de la regex :
import re
texte = "John Smith ([email protected])"
résultat = re.search(r"(\w+) (\w+) \((\w+@\w+\.\w+)\)", texte)
if résultat:
print(f"Nom Complet: {résultat.group(1)} {résultat.group(2)}")
print(f"Email: {résultat.group(3)}")
Cela extrait le nom et l'email du texte.
Références Arrière
Les références arrière permettent de faire référence aux groupes correspondants précédents :
import re
texte = "<h1>Titre</h1><p>Paragraphe</p>"
résultat = re.findall(r"<(\w+)>.*?</\1>", texte)
print(résultat)
Cela correspond aux balises HTML ouvrantes et fermantes.
Alternatives
Le caractère | permet de spécifier des alternatives :
import re
texte = "La couleur du ciel est bleu ou gris"
résultat = re.search(r"bleu|gris", texte)
if résultat:
print(f"Couleur trouvée: {résultat.group()}")
Cela correspond soit à "bleu" soit à "gris".
Ancres
Les ancres spécifient des positions dans le texte :
import re
texte = "Python est génial"
début = re.match(r"^Python", texte)
fin = re.search(r"génial$", texte)
print(f"Commence par Python: {bool(début)}")
print(f"Se termine par génial: {bool(fin)}")
Cela vérifie si le texte commence par "Python" et se termine par "génial".
Syntaxe Spéciale avec Parenthèses
Les parenthèses peuvent être utilisées pour plus que le simple groupement :
- (?:...) crée un groupe non capturant
- (?P
...) crée un groupe nommé - (?=...) crée un lookahead positif
- (?!...) crée un lookahead négatif
import re
texte = "Python version 3.9.5"
résultat = re.search(r"Python (?:version )?(?P<version>\d+\.\d+\.\d+)", texte)
if résultat:
print(f"Version: {résultat.group('version')}")
Cela extrait le numéro de version, que le mot "version" soit présent ou non dans le texte.
Et voilà, mes amis ! Nous avons parcouru la terre des expressions régulières en Python, des concepts de base aux concepts plus avancés. Rappelez-vous, comme tout outil puissant, les regex nécessitent de la pratique pour être maîtrisés. Alors ne vous découragez pas si cela vous semble Overwhelming au début. Continuez à expérimenter, et bientôt vous trouverez des motifs comme un détective pro ! Bon codage !
Credits: Image by storyset