Découvrez la puissance des expressions régulières avec ce tutoriel. Vous utiliserez la bibliothèque re, apprendrez la recherche de motifs, le matching glouton et non glouton, et bien plus encore !
Les expressions régulières, souvent abrégées en regex, sont une suite de caractères permettant de vérifier si un motif est présent dans un texte (chaîne) donné ou non. Si vous avez déjà utilisé des moteurs de recherche, les fonctions rechercher/remplacer des traitements de texte ou des éditeurs, vous avez déjà vu des expressions régulières à l’œuvre. Elles sont utilisées côté serveur pour valider le format des adresses e-mail ou des mots de passe à l’inscription, pour analyser des fichiers texte afin de trouver, remplacer ou supprimer certaines chaînes, etc. Elles facilitent la manipulation de données textuelles, souvent indispensable dans les projets de data science impliquant du text mining.
Ce tutoriel vous guide à travers les concepts essentiels des expressions régulières en Python. Vous commencerez par importer re — la bibliothèque Python qui prend en charge les expressions régulières. Vous verrez ensuite comment utiliser les caractères ordinaires pour effectuer des correspondances, puis les caractères spéciaux (wildcards). Vous apprendrez ensuite à utiliser les répétitions dans vos regex. Vous verrez aussi comment créer des groupes et groupes nommés pour accéder plus facilement aux correspondances. Enfin, vous vous familiariserez avec la notion de matching glouton vs non glouton.
Ça fait déjà beaucoup, c’est pourquoi nous avons inclus un tableau récapitulatif pratique avec de courtes définitions pour ancrer les notions vues. N’hésitez pas à le consulter !
Ce tutoriel couvre également plusieurs fonctions très utiles offertes par la bibliothèque re, comme compile(), search(), findall(), sub() pour chercher et remplacer, split(), et d’autres encore. Vous découvrirez aussi les drapeaux de compilation pour rendre vos regex plus efficaces.
Pour finir, un cas pratique vous permettra de mettre vos connaissances à l’épreuve. En route pour les regex…
Expressions régulières en Python
En Python, les expressions régulières sont prises en charge par le module re. Autrement dit, si vous souhaitez les utiliser dans vos scripts Python, vous devez l’importer avec import :
La bibliothèque re en Python propose plusieurs fonctions qui en font une compétence à maîtriser. Vous en verrez certaines de près dans ce tutoriel.
Motifs de base : caractères ordinaires
Vous pouvez gérer facilement de nombreux motifs de base en Python à l’aide de caractères ordinaires. Les caractères ordinaires sont les expressions régulières les plus simples : ils correspondent exactement à eux-mêmes et n’ont pas de signification spéciale dans la syntaxe des regex.
Exemples : 'A', 'a', 'X', '5'.
Les caractères ordinaires permettent d’effectuer des correspondances exactes simples :
pattern =r"Cookie"
sequence ="Cookie"if re.match(pattern, sequence):print("Match!")else:print("Not a match!")Propulsé par
La plupart des lettres et caractères se correspondent eux-mêmes, comme vous l’avez vu dans l’exemple.
La fonction match() renvoie un objet match si le texte correspond au motif. Sinon, elle renvoie None. Le module re contient aussi d’autres fonctions, que vous découvrirez plus loin.
Pour l’instant, concentrons‑nous sur les caractères ordinaires !
Remarquez le r au début du motif Cookie ? C’est un littéral de chaîne brut (raw string literal). Il modifie la manière dont la chaîne est interprétée : le contenu est stocké tel quel.
Par exemple, \ est juste un antislash lorsqu’il est précédé de r, au lieu d’être interprété comme une séquence d’échappement. Vous verrez ce que cela implique avec les caractères spéciaux. Comme la syntaxe implique parfois des caractères précédés d’un antislash, on utilise le préfixe brut r pour éviter qu’ils ne soient interprétés comme des séquences d’échappement.
Astuce :Vous n’en avez pas besoin dans cet exemple précis ; cependant, c’est une bonne habitude pour rester cohérent.
Caractères génériques : caractères spéciaux
Les caractères spéciaux ne correspondent pas à eux‑mêmes : ils ont une signification particulière dans une expression régulière. Pour simplifier, considérez‑les comme des métacaractères réservés qui représentent autre chose que ce qu’ils affichent.
Voyons des exemples concrets…
Avant cela, les exemples ci‑dessous utilisent deux fonctions : search() et group(). Avec la fonction search, vous parcourez la chaîne fournie pour trouver le premier endroit où l’expression régulière produit une correspondance. La fonction group renvoie la chaîne correspondante. Vous verrez ces deux fonctions plus en détail plus tard.
Revenons aux caractères spéciaux.
. : un point. Correspond à n’importe quel caractère unique sauf le retour à la ligne.
^ : un accent circonflexe. Correspond au début de la chaîne.
Pratique si vous voulez vous assurer qu’un document/une phrase commence par certains caractères.
re.search(r'^Eat',"Eat cake!").group()## However, the code below will not give the same result. Try it for yourself:# re.search(r'^eat', "Let's eat cake!").group()Propulsé par
Pratique si vous voulez vous assurer qu’un document/une phrase se termine par certains caractères.
re.search(r'cake$',"Cake! Let's eat cake").group()## The next search will return the NONE value, try it:# re.search(r'cake$', "Let's get some cake on our way home!").group()Propulsé par
[abc] : correspond à a ou b ou c. [a-zA-Z0-9] : correspond à toute lettre de (a à z) ou (A à Z) ou (0 à 9).
Astuce :Vous pouvez faire correspondre les caractères qui ne sont pas dans un intervalle en complétant l’ensemble. Si le premier caractère de l’ensemble est ^, tous les caractères qui n’en font pas partie seront correspondus.
re.search(r'[0-6]','Number: 5').group()Propulsé par
## Matches any character except 5
re.search(r'Number: [^5]','Number: 0').group()## This will not match and hence a NONE value will be returned#re.search(r'Number: [^5]', 'Number: 5').group()Propulsé par
\ : antislash. Sans doute le métacaractère le plus polyvalent !
Si le caractère suivant l’antislash est un caractère d’échappement reconnu, sa signification spéciale est prise en compte (scénario 1).
Sinon, si le caractère suivant \ n’est pas un caractère d’échappement reconnu, le \ est traité comme un caractère ordinaire (scénario 2).
\ peut précéder tous les métacaractères pour annuler leur signification spéciale (scénario 3).
## (Scenario 1) This treats '\s' as an escape character, '\s' defines a space
re.search(r'Not a\sregular character','Not a regular character').group()Propulsé par
## (Scenario 2) '\' is treated as an ordinary character, because '\r' is not a recognized escape character
re.search(r'Just a \regular character','Just a \regular character').group()Propulsé par
## (Scenario 3) '\s' is escaped using an extra `\` so its interpreted as a literal string '\s'
re.search(r'Just a \\sregular character','Just a \sregular character').group()Propulsé par
Il existe un ensemble de séquences spéciales prédéfinies commençant par « \ », très utiles pour la recherche et les correspondances. Voyons‑en quelques‑unes…
\w — « w » minuscule. Correspond à toute lettre, chiffre ou soulignement. \W — « W » majuscule. Correspond à tout caractère qui n’appartient pas à \w (w minuscule).
print("Lowercase w:", re.search(r'Co\wk\we','Cookie').group())## Matches any character except single letter, digit or underscoreprint("Uppercase W:", re.search(r'C\Wke','C@ke').group())## Uppercase W won't match single letter, digitprint("Uppercase W won't match, and return:", re.search(r'Co\Wk\We','Cookie'))Propulsé par
Lowercase w: Cookie
Uppercase W:C@ke
Uppercase W won't match, and return: None
Propulsé par
\s — « s » minuscule. Correspond à un espace blanc : espace, retour à la ligne, tabulation, retour chariot. \S — « S » majuscule. Correspond à tout caractère qui n’appartient pas à \s (s minuscule).
print("Lowercase s:", re.search(r'Eat\scake','Eat cake').group())print("Uppercase S:", re.search(r'cook\Se',"Let's eat cookie").group())Propulsé par
Lowercase s: Eat cake
Uppercase S: cookie
Propulsé par
\d — « d » minuscule. Correspond à un chiffre décimal 0‑9. \D — « D » majuscule. Correspond à tout caractère qui n’est pas un chiffre décimal.
# Example for \dprint("How many cookies do you want? ", re.search(r'\d+','100 cookies').group())Propulsé par
Le symbole + utilisé après \d dans l’exemple ci‑dessus sert à la répétition. Vous verrez cela plus en détail dans la section répétitions…
\t — « t » minuscule. Correspond à une tabulation. \n — « n » minuscule. Correspond à un saut de ligne. \r — « r » minuscule. Correspond à un retour chariot. \A — « A » majuscule. Correspond uniquement au début de la chaîne. Fonctionne aussi sur plusieurs lignes. \Z — « Z » majuscule. Correspond uniquement à la fin de la chaîne. Astuce :^ et \A sont équivalents, tout comme $ et \Z, sauf en mode MULTILINE. Voir la section drapeaux.
\b — « b » minuscule. Correspond uniquement au début ou à la fin d’un mot.
# Example for \tprint("\\t (TAB) example: ", re.search(r'Eat\tcake','Eat cake').group())# Example for \bprint("\\b match gives: ",re.search(r'\b[A-E]ookie','Cookie').group())Propulsé par
\t(TAB) example: Eat cake
\b match gives: CookiePropulsé par
Répétitions
Chercher de longs motifs dans une séquence peut vite devenir fastidieux. Heureusement, le module re gère les répétitions grâce aux caractères spéciaux suivants :
+ — Vérifie si le caractère précédent apparaît une ou plusieurs fois à partir de cette position.
re.search(r'Co+kie','Cooookie').group()Propulsé par
Les qualificateurs + et * sont dits gloutons. Vous verrez ce que cela signifie juste après.
Regroupement dans les expressions régulières
La fonctionnalité de groupe permet d’extraire des parties du texte correspondant. Les portions d’un motif entourées de parenthèses () sont appelées groupes. Les parenthèses ne changent pas ce qui est correspond, elles structurent la séquence trouvée. Vous utilisez la fonction group() tout au long des exemples de ce tutoriel. L’appel simple match.group() sans argument renvoie toujours l’intégralité du texte trouvé.
Illustrons avec un exemple simple. Imaginez que vous validiez des adresses e‑mail et vouliez vérifier le nom d’utilisateur et l’hôte. C’est là que vous créez des groupes distincts dans le texte correspondant.
statement ='Please contact us at: [email protected]'match= re.search(r'([\w\.-]+)@([\w\.-]+)', statement)if statement:print("Email address:",match.group())# The whole matched textprint("Username:",match.group(1))# The username (group 1)print("Host:",match.group(2))# The host (group 2)Propulsé par
Email address: support@datacamp.com
Username: support
Host: datacamp.com
Propulsé par
Une autre manière d’obtenir le même résultat consiste à utiliser des crochets <> pour créer des groupes nommés. Les groupes nommés rendent votre code plus lisible. La syntaxe est : (?P<name>...). Remplacez name par le nom souhaité pour votre groupe. Les ... représentent le reste de la syntaxe de correspondance. Voyez‑le à l’œuvre avec le même exemple…
statement ='Please contact us at: [email protected]'match= re.search(r'(?P<email>(?P<username>[\w\.-]+)@(?P<host>[\w\.-]+))', statement)if statement:print("Email address:",match.group('email'))print("Username:",match.group('username'))print("Host:",match.group('host'))Propulsé par
Email address: support@datacamp.com
Username: support
Host: datacamp.com
Propulsé par
Astuce :Vous pouvez toujours accéder aux groupes nommés via leurs indices numériques. Mais plus le nombre de groupes augmente, plus cela devient difficile à gérer. Prenez l’habitude d’utiliser des groupes nommés.
Matching glouton vs non glouton
Lorsqu’un métacaractère capture le plus de texte possible, on parle de « matching glouton ». C’est le comportement par défaut des regex, mais il n’est pas toujours souhaitable :
pattern ="cookie"
sequence ="Cake and cookie"
heading =r'<h1>TITLE</h1>'
re.match(r'<.*>', heading).group()Propulsé par
Le motif <.*> a fait correspondre toute la chaîne, jusqu’à la deuxième occurrence de >.
Cependant, si vous ne vouliez faire correspondre que la première balise <h1>, vous pourriez utiliser le qualificateur non glouton *? qui capture le moins de texte possible.
Ajouter ? après le qualificateur le rend non glouton : il correspond au minimum de caractères. Avec <.*?>, vous n’obtenez qu’une correspondance sur <h1>.
heading =r'<h1>TITLE</h1>'
re.match(r'<.*?>', heading).group()Propulsé par
Vous avez déjà parcouru un bon chemin avec les expressions régulières. C’est un lot d’informations à assimiler ! Le tableau suivant résume tout ce que vous avez vu jusqu’ici. Ne vous inquiétez pas si tous les métacaractères ne sont pas encore limpides. Avec le temps et la pratique, vous saurez les différencier et choisir le bon au bon moment…
Un point. Correspond à n’importe quel caractère unique sauf le retour à la ligne.
^
Accent circonflexe. Correspond au début de la chaîne.
\A
A majuscule. Correspond uniquement au début de la chaîne.
$
Signe dollar. Correspond à la fin de la chaîne.
\Z
Z majuscule. Correspond uniquement à la fin de la chaîne.
[ ]
Correspond à l’ensemble des caractères spécifiés entre crochets.
\
∙ Si le caractère suivant l’antislash est un échappement reconnu, sa signification spéciale s’applique. ∙ Sinon, l’antislash est traité comme un caractère ordinaire. ∙ Peut précéder tout métacaractère pour annuler sa signification spéciale.
\w
w minuscule. Correspond à toute lettre, chiffre ou soulignement.
\W
W majuscule. Correspond à tout caractère qui n’appartient pas à \w (w minuscule).
\s
s minuscule. Correspond à un caractère d’espace blanc : espace, saut de ligne, tabulation, retour chariot.
\S
S majuscule. Correspond à tout caractère qui n’appartient pas à \s (s minuscule).
\d
d minuscule. Correspond à un chiffre décimal 0‑9.
\D
D majuscule. Correspond à tout caractère qui n’est pas un chiffre décimal.
\t
t minuscule. Correspond à une tabulation.
\n
n minuscule. Correspond à un saut de ligne.
\r
r minuscule. Correspond à un retour chariot.
\b
b minuscule. Correspond uniquement au début ou à la fin d’un mot.
+
Vérifie si le caractère précédent apparaît une ou plusieurs fois.
*
Vérifie si le caractère précédent apparaît zéro ou plusieurs fois.
?
∙ Vérifie si le caractère précédent apparaît exactement zéro ou une fois. ∙ Spécifie une version non gloutonne de +, *
{ }
Vérifie un nombre explicite de répétitions.
( )
Crée un groupe lors des correspondances.
< >
Crée un groupe nommé lors des correspondances.
Vous avez vu l’essentiel des regex ! D’autres notions peuvent toutefois vous aider à créer des expressions régulières efficaces pour la recherche et la mise en correspondance.
Astuce :Bien que très puissantes, les expressions régulières peuvent devenir illisibles si elles sont trop longues ou alambiquées. Préférez des motifs compréhensibles et maintenables.
Fonctions proposées par « re »
La bibliothèque re en Python fournit plusieurs fonctions pour vous simplifier la vie. Vous en avez déjà vu certaines, comme re.search() et re.match(). Voyons-en d’autres…
compile(pattern, flags=0)
En Python, les expressions régulières sont manipulées comme des chaînes. Toutefois, avec compile(), vous pouvez compiler un motif en un objet expression régulière. Lorsque vous devez réutiliser plusieurs fois une expression dans un même programme, la compiler avec compile() puis réutiliser l’objet obtenu est plus efficace que de conserver une simple chaîne, car les versions compilées des motifs les plus récents sont mises en cache par compile() et par les fonctions de correspondance au niveau du module.
pattern = re.compile(r"cookie")
sequence ="Cake and cookie"
pattern.search(sequence).group()Propulsé par
Cette fonction parcourt la chaîne fournie à la recherche du premier emplacement où l’expression régulière produit une correspondance. Elle renvoie un objet match si trouvé, sinon None si aucune position ne correspond. Notez que None est différent d’une correspondance de longueur nulle trouvée à un endroit de la chaîne.
pattern ="cookie"
sequence ="Cake and cookie"
re.search(pattern, sequence)Propulsé par
<re.Match object; span=(9,15), match='cookie'>Propulsé par
match(pattern, string, flags=0)
Renvoie un objet match si zéro ou plusieurs caractères au début de la chaîne correspondent au motif. Sinon, renvoie None si la chaîne ne correspond pas au motif donné.
pattern ="C"
sequence1 ="IceCream"
sequence2 ="Cake"# No match since "C" is not at the start of "IceCream"print("Sequence 1: ", re.match(pattern, sequence1))print("Sequence 2: ", re.match(pattern,sequence2).group())Propulsé par
match() vérifie une correspondance uniquement au début de la chaîne (par défaut), tandis que search() cherche une correspondance n’importe où dans la chaîne.
findall(pattern, string, flags=0)
Retourne toutes les correspondances possibles dans l’ensemble de la séquence, sous forme de liste de chaînes. Chaque chaîne renvoyée représente une correspondance.
statement ="Please contact us at: [email protected], [email protected]"#'addresses' is a list that stores all the possible match
addresses = re.findall(r'[\w\.-]+@[\w\.-]+', statement)for address in addresses:print(address)Propulsé par
support@datacamp.com
xyz@datacamp.com
Propulsé par
finditer(string, [position, end_position])
Semblable à findall() : trouve toutes les correspondances possibles dans la séquence, mais renvoie des objets match sous forme d’itérateur.
Astuce :finditer() est un excellent choix lorsque vous voulez récupérer davantage d’informations sur votre recherche. Les objets match renvoyés contiennent non seulement la séquence trouvée, mais aussi leurs positions dans le texte d’origine.
statement ="Please contact us at: [email protected], [email protected]"#'addresses' is a list that stores all the possible match
addresses = re.finditer(r'[\w\.-]+@[\w\.-]+', statement)for address in addresses:print(address)Propulsé par
sub() est la fonction de substitution. Elle renvoie la chaîne obtenue en remplaçant les occurrences non chevauchantes les plus à gauche du motif par la valeur repl. Si le motif n’est pas trouvé, la chaîne est renvoyée telle quelle.
subn() est similaire à sub(), mais renvoie un tuple contenant la nouvelle chaîne et le nombre de remplacements effectués.
Please contact us at: support@datacamp.com
Propulsé par
split(string, [maxsplit = 0])
Scinde la chaîne partout où le motif correspond et renvoie une liste. Si l’argument optionnel maxsplit est non nul, au plus maxsplit découpages sont effectués.
start() — Renvoie l’indice de début de la correspondance. end() — Renvoie l’indice où la correspondance se termine. span() — Renvoie un tuple contenant les positions (début, fin) de la correspondance.
pattern = re.compile('COOKIE', re.IGNORECASE)match= pattern.search("I am not a cookie monster")print("Start index:",match.start())print("End index:",match.end())print("Tuple:",match.span())Propulsé par
Start index:11
End index:17Tuple:(11,17)Propulsé par
Drapeaux de compilation
Avez‑vous remarqué re.IGNORECASE dans le dernier exemple ? Avez‑vous deviné son importance ?
Le comportement d’une expression peut être modifié par des drapeaux. Vous pouvez ajouter des drapeaux en argument supplémentaire aux différentes fonctions vues dans ce tutoriel. Parmi les plus utiles :
IGNORECASE (I) — Autorise les correspondances insensibles à la casse. DOTALL (S) — Permet à . de correspondre à n’importe quel caractère, y compris le saut de ligne. MULTILINE (M) — Permet aux ancres début (^) et fin ($) de chaîne de correspondre aussi aux fins/débuts de lignes. VERBOSE (X) — Autorise les espaces et commentaires dans une regex pour la rendre plus lisible.
statement ="Please contact us at: [email protected], [email protected]"# Using the VERBOSE flag helps understand complex regular expressions
pattern = re.compile(r"""
[\w\.-]+ #First part
@ #Matches @ sign within email addresses
datacamp.com #Domain
""", re.X | re.I)
addresses = re.findall(pattern, statement)for address in addresses:print("Address: ", address)Propulsé par
Address: support@DataCamp.com
Address: xyz@DATACAMP.com
Propulsé par
Astuce :Vous pouvez combiner plusieurs drapeaux avec l’opérateur OU bit à bit |.
Cas pratique : travailler avec des expressions régulières
Vous avez vu comment fonctionnent les regex en Python à travers des exemples ; passons à la pratique ! Dans ce cas d’usage, vous allez mobiliser tout ce que vous avez appris.
Vous travaillerez avec la première partie d’un e‑book gratuit intitulé « The Idiot », de Fiodor Dostoïevski (Project Gutenberg). Le roman raconte l’histoire du prince (Kniaz) Lev Nikolaïevitch Mychkine, un homme candide dont la bonté et la simplicité sont trop souvent prises pour un manque d’intelligence et de discernement. Le titre fait ironiquement référence à ce malentendu.
Vous écrirez des expressions régulières pour analyser le texte et réaliser quelques exercices.
import re
import requests
the_idiot_url ='https://www.gutenberg.org/files/2638/2638-0.txt'defget_book(url):# Sends a http request to get the text from project Gutenberg
raw = requests.get(url).text
# Discards the metadata from the beginning of the book
start = re.search(r"\*\*\* START OF THIS PROJECT GUTENBERG EBOOK .* \*\*\*",raw ).end()# Discards the text starting Part 2 of the book
stop = re.search(r"II", raw).start()# Keeps the relevant text
text = raw[start:stop]return text
defpreprocess(sentence):return re.sub('[^A-Za-z0-9.]+',' ', sentence).lower()
book = get_book(the_idiot_url)
processed_book = preprocess(book)#print(processed_book)Propulsé par
Exercice : comptez le nombre d’occurrences du pronom « the » dans le corpus. Indice : utilisez la fonction len().
len(re.findall(r'the', processed_book))Propulsé par
Exercice : quels sont les mots reliés par '--' dans le corpus ? À vous de jouer ! Partagez vos réponses dans les commentaires ci‑dessous.
Bravo !
Vous êtes arrivé au bout de ce tutoriel sur les expressions régulières en Python ! Il y a encore beaucoup à explorer dans votre parcours data science avec Python.
Les regex peuvent jouer un rôle clé dans la phase de prétraitement des données. Découvrez le cours Cleaning Data in Python de DataCamp. Vous y apprendrez à mieux explorer vos données en les organisant et en les nettoyant pour l’analyse. Un cas pratique final vous permettra de mettre en œuvre vos nouvelles compétences.
Initiez-vous aux structures de données de Python : apprenez-en plus sur les types de données et les structures de données primitives et non primitives, telles que les chaînes de caractères, les listes, les piles, etc.
Tutoriel complet d'introduction aux boucles Python. Apprenez et pratiquez les boucles while et for, les boucles imbriquées, les mots-clés break et continue, la fonction range et bien plus encore.
Découvrez les fonctions et méthodes des listes Python. Veuillez suivre les exemples de code pour list() et d'autres fonctions et méthodes Python dès maintenant.
Les expressions régulières, souvent abrégées en regex, sont une suite de caractères permettant de vérifier si un motif est présent dans un texte (chaîne) donné ou non. Si vous avez déjà utilisé des moteurs de recherche, les fonctions rechercher/remplacer des traitements de texte ou des éditeurs, vous avez déjà vu des expressions régulières à l’œuvre. Elles sont utilisées côté serveur pour valider le format des adresses e-mail ou des mots de passe à l’inscription, pour analyser des fichiers texte afin de trouver, remplacer ou supprimer certaines chaînes, etc. Elles facilitent la manipulation de données textuelles, souvent indispensable dans les projets de data science impliquant du text mining.
Ce tutoriel vous guide à travers les concepts essentiels des expressions régulières en Python. Vous commencerez par importer
re— la bibliothèque Python qui prend en charge les expressions régulières. Vous verrez ensuite comment utiliser les caractères ordinaires pour effectuer des correspondances, puis les caractères spéciaux (wildcards). Vous apprendrez ensuite à utiliser les répétitions dans vos regex. Vous verrez aussi comment créer des groupes et groupes nommés pour accéder plus facilement aux correspondances. Enfin, vous vous familiariserez avec la notion de matching glouton vs non glouton.Ça fait déjà beaucoup, c’est pourquoi nous avons inclus un tableau récapitulatif pratique avec de courtes définitions pour ancrer les notions vues. N’hésitez pas à le consulter !
Ce tutoriel couvre également plusieurs fonctions très utiles offertes par la bibliothèque
re, commecompile(),search(),findall(),sub()pour chercher et remplacer,split(), et d’autres encore. Vous découvrirez aussi les drapeaux de compilation pour rendre vos regex plus efficaces.Pour finir, un cas pratique vous permettra de mettre vos connaissances à l’épreuve. En route pour les regex…
Expressions régulières en Python
En Python, les expressions régulières sont prises en charge par le module re. Autrement dit, si vous souhaitez les utiliser dans vos scripts Python, vous devez l’importer avec
import:La bibliothèque
reen Python propose plusieurs fonctions qui en font une compétence à maîtriser. Vous en verrez certaines de près dans ce tutoriel.Motifs de base : caractères ordinaires
Vous pouvez gérer facilement de nombreux motifs de base en Python à l’aide de caractères ordinaires. Les caractères ordinaires sont les expressions régulières les plus simples : ils correspondent exactement à eux-mêmes et n’ont pas de signification spéciale dans la syntaxe des regex.
Exemples : 'A', 'a', 'X', '5'.
Les caractères ordinaires permettent d’effectuer des correspondances exactes simples :
La plupart des lettres et caractères se correspondent eux-mêmes, comme vous l’avez vu dans l’exemple.
La fonction
match()renvoie un objet match si le texte correspond au motif. Sinon, elle renvoieNone. Le modulerecontient aussi d’autres fonctions, que vous découvrirez plus loin.Pour l’instant, concentrons‑nous sur les caractères ordinaires !
Remarquez le
rau début du motifCookie?C’est un littéral de chaîne brut (raw string literal). Il modifie la manière dont la chaîne est interprétée : le contenu est stocké tel quel.
Par exemple,
\est juste un antislash lorsqu’il est précédé der, au lieu d’être interprété comme une séquence d’échappement. Vous verrez ce que cela implique avec les caractères spéciaux. Comme la syntaxe implique parfois des caractères précédés d’un antislash, on utilise le préfixe brutrpour éviter qu’ils ne soient interprétés comme des séquences d’échappement.Astuce : Vous n’en avez pas besoin dans cet exemple précis ; cependant, c’est une bonne habitude pour rester cohérent.
Caractères génériques : caractères spéciaux
Les caractères spéciaux ne correspondent pas à eux‑mêmes : ils ont une signification particulière dans une expression régulière. Pour simplifier, considérez‑les comme des métacaractères réservés qui représentent autre chose que ce qu’ils affichent.
Voyons des exemples concrets…
Avant cela, les exemples ci‑dessous utilisent deux fonctions :
search()etgroup().Avec la fonction search, vous parcourez la chaîne fournie pour trouver le premier endroit où l’expression régulière produit une correspondance.
La fonction group renvoie la chaîne correspondante. Vous verrez ces deux fonctions plus en détail plus tard.
Revenons aux caractères spéciaux.
.: un point. Correspond à n’importe quel caractère unique sauf le retour à la ligne.^: un accent circonflexe. Correspond au début de la chaîne.Pratique si vous voulez vous assurer qu’un document/une phrase commence par certains caractères.
$: correspond à la fin de la chaîne.Pratique si vous voulez vous assurer qu’un document/une phrase se termine par certains caractères.
[abc]: correspond à a ou b ou c.[a-zA-Z0-9]: correspond à toute lettre de (a à z) ou (A à Z) ou (0 à 9).Astuce : Vous pouvez faire correspondre les caractères qui ne sont pas dans un intervalle en complétant l’ensemble. Si le premier caractère de l’ensemble est
^, tous les caractères qui n’en font pas partie seront correspondus.\: antislash.Sans doute le métacaractère le plus polyvalent !
\n’est pas un caractère d’échappement reconnu, le\est traité comme un caractère ordinaire (scénario 2).\peut précéder tous les métacaractères pour annuler leur signification spéciale (scénario 3).Il existe un ensemble de séquences spéciales prédéfinies commençant par « \ », très utiles pour la recherche et les correspondances. Voyons‑en quelques‑unes…
\w— « w » minuscule. Correspond à toute lettre, chiffre ou soulignement.\W— « W » majuscule. Correspond à tout caractère qui n’appartient pas à\w(w minuscule).\s— « s » minuscule. Correspond à un espace blanc : espace, retour à la ligne, tabulation, retour chariot.\S— « S » majuscule. Correspond à tout caractère qui n’appartient pas à\s(s minuscule).\d— « d » minuscule. Correspond à un chiffre décimal 0‑9.\D— « D » majuscule. Correspond à tout caractère qui n’est pas un chiffre décimal.Le symbole
+utilisé après\ddans l’exemple ci‑dessus sert à la répétition. Vous verrez cela plus en détail dans la section répétitions…\t— « t » minuscule. Correspond à une tabulation.\n— « n » minuscule. Correspond à un saut de ligne.\r— « r » minuscule. Correspond à un retour chariot.\A— « A » majuscule. Correspond uniquement au début de la chaîne. Fonctionne aussi sur plusieurs lignes.\Z— « Z » majuscule. Correspond uniquement à la fin de la chaîne.Astuce :
^et\Asont équivalents, tout comme$et\Z, sauf en mode MULTILINE. Voir la section drapeaux.\b— « b » minuscule. Correspond uniquement au début ou à la fin d’un mot.Répétitions
Chercher de longs motifs dans une séquence peut vite devenir fastidieux. Heureusement, le module
regère les répétitions grâce aux caractères spéciaux suivants :+— Vérifie si le caractère précédent apparaît une ou plusieurs fois à partir de cette position.*— Vérifie si le caractère précédent apparaît zéro ou plusieurs fois.?— Vérifie si le caractère précédent apparaît exactement zéro ou une fois.Mais que faire si vous souhaitez vérifier un nombre exact de répétitions ?
Par exemple, valider un numéro de téléphone dans une application. Le module
rele gère très bien grâce aux expressions suivantes :{x}— Répéter exactement x fois.{x,}— Répéter au moins x fois.{x, y}— Répéter au moins x fois mais pas plus de y fois.Les qualificateurs
+et*sont ditsgloutons. Vous verrez ce que cela signifie juste après.Regroupement dans les expressions régulières
La fonctionnalité de groupe permet d’extraire des parties du texte correspondant. Les portions d’un motif entourées de parenthèses
()sont appelées groupes. Les parenthèses ne changent pas ce qui est correspond, elles structurent la séquence trouvée. Vous utilisez la fonctiongroup()tout au long des exemples de ce tutoriel. L’appel simplematch.group()sans argument renvoie toujours l’intégralité du texte trouvé.Illustrons avec un exemple simple. Imaginez que vous validiez des adresses e‑mail et vouliez vérifier le nom d’utilisateur et l’hôte. C’est là que vous créez des groupes distincts dans le texte correspondant.
Une autre manière d’obtenir le même résultat consiste à utiliser des crochets
<>pour créer des groupes nommés. Les groupes nommés rendent votre code plus lisible. La syntaxe est :(?P<name>...). Remplaceznamepar le nom souhaité pour votre groupe. Les...représentent le reste de la syntaxe de correspondance. Voyez‑le à l’œuvre avec le même exemple…Astuce :Vous pouvez toujours accéder aux groupes nommés via leurs indices numériques. Mais plus le nombre de groupes augmente, plus cela devient difficile à gérer. Prenez l’habitude d’utiliser des groupes nommés.Matching glouton vs non glouton
Lorsqu’un métacaractère capture le plus de texte possible, on parle de « matching glouton ». C’est le comportement par défaut des regex, mais il n’est pas toujours souhaitable :
Le motif
<.*>a fait correspondre toute la chaîne, jusqu’à la deuxième occurrence de>.Cependant, si vous ne vouliez faire correspondre que la première balise
<h1>, vous pourriez utiliser le qualificateur non glouton*?qui capture le moins de texte possible.Ajouter
?après le qualificateur le rend non glouton : il correspond au minimum de caractères. Avec<.*?>, vous n’obtenez qu’une correspondance sur<h1>.Tableau récapitulatif
Vous avez déjà parcouru un bon chemin avec les expressions régulières. C’est un lot d’informations à assimiler ! Le tableau suivant résume tout ce que vous avez vu jusqu’ici. Ne vous inquiétez pas si tous les métacaractères ne sont pas encore limpides. Avec le temps et la pratique, vous saurez les différencier et choisir le bon au bon moment…
Ce tutoriel ne couvre pas toutes les séquences spéciales disponibles en Python. Consultez la documentation de la bibliothèque standard pour la liste complète.
∙ Sinon, l’antislash est traité comme un caractère ordinaire.
∙ Peut précéder tout métacaractère pour annuler sa signification spéciale.
\w(w minuscule).\s(s minuscule).∙ Spécifie une version non gloutonne de +, *
Vous avez vu l’essentiel des regex ! D’autres notions peuvent toutefois vous aider à créer des expressions régulières efficaces pour la recherche et la mise en correspondance.
Astuce : Bien que très puissantes, les expressions régulières peuvent devenir illisibles si elles sont trop longues ou alambiquées. Préférez des motifs compréhensibles et maintenables.
Fonctions proposées par « re »
La bibliothèque
reen Python fournit plusieurs fonctions pour vous simplifier la vie. Vous en avez déjà vu certaines, commere.search()etre.match(). Voyons-en d’autres…compile(pattern, flags=0)En Python, les expressions régulières sont manipulées comme des chaînes. Toutefois, avec
compile(), vous pouvez compiler un motif en un objet expression régulière. Lorsque vous devez réutiliser plusieurs fois une expression dans un même programme, la compiler aveccompile()puis réutiliser l’objet obtenu est plus efficace que de conserver une simple chaîne, car les versions compilées des motifs les plus récents sont mises en cache parcompile()et par les fonctions de correspondance au niveau du module.search(pattern, string, flags=0)Cette fonction parcourt la chaîne fournie à la recherche du premier emplacement où l’expression régulière produit une correspondance. Elle renvoie un objet match si trouvé, sinon
Nonesi aucune position ne correspond. Notez queNoneest différent d’une correspondance de longueur nulle trouvée à un endroit de la chaîne.match(pattern, string, flags=0)Renvoie un objet match si zéro ou plusieurs caractères au début de la chaîne correspondent au motif. Sinon, renvoie
Nonesi la chaîne ne correspond pas au motif donné.search()versusmatch()match()vérifie une correspondance uniquement au début de la chaîne (par défaut), tandis quesearch()cherche une correspondance n’importe où dans la chaîne.findall(pattern, string, flags=0)Retourne toutes les correspondances possibles dans l’ensemble de la séquence, sous forme de liste de chaînes. Chaque chaîne renvoyée représente une correspondance.
finditer(string, [position, end_position])Semblable à
findall(): trouve toutes les correspondances possibles dans la séquence, mais renvoie des objets match sous forme d’itérateur.Astuce :
finditer()est un excellent choix lorsque vous voulez récupérer davantage d’informations sur votre recherche. Les objets match renvoyés contiennent non seulement la séquence trouvée, mais aussi leurs positions dans le texte d’origine.sub(pattern, repl, string, count=0, flags=0)subn(pattern, repl, string, count=0)sub()est la fonction de substitution. Elle renvoie la chaîne obtenue en remplaçant les occurrences non chevauchantes les plus à gauche du motif par la valeurrepl. Si le motif n’est pas trouvé, la chaîne est renvoyée telle quelle.subn()est similaire àsub(), mais renvoie un tuple contenant la nouvelle chaîne et le nombre de remplacements effectués.split(string, [maxsplit = 0])Scinde la chaîne partout où le motif correspond et renvoie une liste. Si l’argument optionnel
maxsplitest non nul, au plusmaxsplitdécoupages sont effectués.start()— Renvoie l’indice de début de la correspondance.end()— Renvoie l’indice où la correspondance se termine.span()— Renvoie un tuple contenant les positions (début, fin) de la correspondance.Drapeaux de compilation
Avez‑vous remarqué
re.IGNORECASEdans le dernier exemple ? Avez‑vous deviné son importance ?Le comportement d’une expression peut être modifié par des drapeaux. Vous pouvez ajouter des drapeaux en argument supplémentaire aux différentes fonctions vues dans ce tutoriel. Parmi les plus utiles :
IGNORECASE (I) — Autorise les correspondances insensibles à la casse.
DOTALL (S) — Permet à . de correspondre à n’importe quel caractère, y compris le saut de ligne.
MULTILINE (M) — Permet aux ancres début (^) et fin ($) de chaîne de correspondre aussi aux fins/débuts de lignes.
VERBOSE (X) — Autorise les espaces et commentaires dans une regex pour la rendre plus lisible.
Astuce : Vous pouvez combiner plusieurs drapeaux avec l’opérateur OU bit à bit
|.Cas pratique : travailler avec des expressions régulières
Vous avez vu comment fonctionnent les regex en Python à travers des exemples ; passons à la pratique ! Dans ce cas d’usage, vous allez mobiliser tout ce que vous avez appris.
Vous travaillerez avec la première partie d’un e‑book gratuit intitulé « The Idiot », de Fiodor Dostoïevski (Project Gutenberg). Le roman raconte l’histoire du prince (Kniaz) Lev Nikolaïevitch Mychkine, un homme candide dont la bonté et la simplicité sont trop souvent prises pour un manque d’intelligence et de discernement. Le titre fait ironiquement référence à ce malentendu.
Vous écrirez des expressions régulières pour analyser le texte et réaliser quelques exercices.
len()."") dans le corpus.'--'dans le corpus ?À vous de jouer ! Partagez vos réponses dans les commentaires ci‑dessous.
Bravo !
Vous êtes arrivé au bout de ce tutoriel sur les expressions régulières en Python ! Il y a encore beaucoup à explorer dans votre parcours data science avec Python.
Les regex peuvent jouer un rôle clé dans la phase de prétraitement des données. Découvrez le cours Cleaning Data in Python de DataCamp. Vous y apprendrez à mieux explorer vos données en les organisant et en les nettoyant pour l’analyse. Un cas pratique final vous permettra de mettre en œuvre vos nouvelles compétences.
Consultez aussi notre Tutoriel sur le remplacement de chaînes en Python.