CPGE Oujda
Spé
Initiation aux
expressions régulières
Si on demande à l'utilisateur de fournir un numéro de téléphone ? Qu'est-ce
qui l'empêche de taper n'importe quoi ? Si on lui demande de fournir une
adresse e-mail et qu'il tape quelque chose d'invalide, que va-t-il se passer ?
Si ce cas n'est pas géré, vous risquez d'avoir un problème. Les expressions
régulières sont un moyen de rechercher, d'isoler ou de remplacer des
expressions dans une chaîne.
Quelques éléments de syntaxe pour les expressions
régulières
Le module re, nous permet de faire des recherches très
précises dans des chaînes de caractères et de remplacer des éléments de nos
chaînes, le tout en fonction de critères particuliers. Ces critères, ce sont
nos expressions régulières. Pour nous, elles se présentent sous la forme
de chaînes de caractères.
Rechercher au début ou à la fin de la chaîne
Vous pouvez rechercher au début de la chaîne en plaçant en tête de votre regex (abréviation de Regular
Expression) le signe d'accent circonflexe ^. Si, par exemple, vous
voulez rechercher la syllabe cha en début de votre chaîne, vous
écrirez donc l'expression ^cha. Cette
expression sera trouvée dans la chaîne 'chaton' mais pas dans la chaîne 'achat'. Pour matérialiser la fin de la chaîne, vous
utiliserez le signe $. Ainsi,
l'expression q$ sera trouvée
uniquement si votre chaîne se termine par la lettre q minuscule.
Contrôler le nombre d'occurrences
exemple : chat*
Cela signifie que notre lettre t pourra se retrouver 0, 1, 2, … fois dans notre
chaîne. Ex : 'herbe
à chat', 'chatterton', 'chattttttttt'…
Un autre exemple ? :
bat*e : Cette
expression est trouvée dans les chaînes suivantes : 'bateau', 'batteur' .
Dans nos exemples, le signe * n'agit que sur la lettre qui le précède directement,
pas sur les autres lettres qui figurent avant ou après.
Il existe d'autres signes permettant de contrôler le nombre d'occurrences
d'une lettre.
|
Signe |
Explication |
Expression |
Chaînes contenant l'expression |
|
* |
0, 1 ou plus |
abc* |
'ab', 'abc', 'abcc', 'abcccccc' |
|
+ |
1 ou plus |
abc+ |
'abc', 'abcc', 'abccc' |
|
? |
0 ou 1 |
abc? |
'ab', 'abc' |
Vous pouvez également contrôler précisément le nombre d'occurrences grâce
aux accolades :
Les classes de caractères
Vous pouvez préciser entre crochets plusieurs caractères ou classes de
caractères. Par exemple, si vous écrivez [abcd], cela signifie
: l'une des lettres parmi a, b, c et d.
Pour exprimer des classes, vous pouvez utiliser le tiret - entre deux
lettres. Par exemple, l'expression [A-Z] signifie « une lettre majuscule ». Vous pouvez
préciser plusieurs classes ou possibilités dans votre expression. Ainsi,
l'expression [A-Za-z0-9] signifie « une lettre, majuscule ou minuscule, ou un
chiffre ». Vous pouvez aussi contrôler
l'occurrence des classes . Si vous voulez par exemple
rechercher 5 lettres majuscules qui se suivent dans une chaîne, votre
expression sera [A-Z]{5}.
Les groupes
si vous voulez appliquer ce contrôle d'occurrence à plusieurs
caractères, vous allez placer ces caractères entre parenthèses. (cha){2,5}
Cette expression sera vérifiée pour les chaînes contenant la séquence 'cha' répétée entre deux et cinq fois. Les séquences 'cha' doivent se suivre naturellement.
Les groupes sont également utiles pour remplacer des portions de notre chaîne .
Le module re :
Le module re a été
spécialement conçu pour travailler avec les expressions régulières (Regular Expressions). Il définit plusieurs
fonctions utiles ainsi que des objets
propres pour modéliser des expressions.
Chercher dans une chaîne
Nous allons pour ce faire utiliser la fonction search du module re. Bien entendu,
pour pouvoir l'utiliser, il faut l'importer. >>> import re
La fonction search attend deux paramètres obligatoires : l'expression
régulière, sous la forme d'une chaîne, et la chaîne de caractères dans laquelle
on recherche cette expression. Si l'expression est trouvée, la fonction renvoie
un objet symbolisant l'expression recherchée. Sinon, elle renvoie None.
Certains caractères spéciaux dans nos expressions régulières sont modélisés
par l'anti-slash \. pour écrire le caractère
spécial \w, vous allez
devoir écrire \\w.
on peut aussi mettre un r avant d'écrire des chaînes contenant des expressions.
>>> re.search(r"abc", "abcdef") à <_sre.SRE_Match object at 0x00AC1640>
>>> re.search(r"abc", "abacadaeaf")
>>> re.search(r"abc*", "ab") à<_sre.SRE_Match object at 0x00AC1800>
>>> re.search(r"abc*", "abccc") à <_sre.SRE_Match object at 0x00AC1640>
>>> re.search(r"chat*", "chateau") à <_sre.SRE_Match object at 0x00AC1800>
si l'expression est trouvée dans la chaîne, un objet de
la classe _sre.SRE_Match est renvoyé. Si l'expression n'est
pas trouvée, la fonction renvoie None.
if re.match(expression, chaine) is not None:# Si l'expression est dans la chaîne
# Ou alors, plus intuitivement if re.match(expression, chaine):
par exemple, comment obliger l'utilisateur à saisir un
numéro de téléphone ?
Notre regex doit vérifier qu'une chaîne est un
numéro de téléphone. L'utilisateur peut saisir un numéro de différentes façons
:
Autrement dit :
Voici la regex:
^0[0-9]([ .-]?[0-9]{2}){4}$
import re
chaine = ""
expression = r"^0[0-9]([ .-]?[0-9]{2}){4}$"
while re.search(expression, chaine) is None:
chaine = input("Saisissez un numéro de téléphone (valide) :")
Compilation d'expressions régulières
Il est aussi commode de préalablement compiler l'expression régulière à
l'aide de la fonction compile() qui renvoie un objet de type
expression régulière :
>>> regex = re.compile("^tigre")
>>> regex
<_sre.SRE_Pattern object at 0x7fefdafd0df0>
On peut alors utiliser directement cet objet avec la méthode search() :
>>> animaux = "girafe tigre singe"
>>> regex.search(animaux)
>>> animaux = "tigre singe"
>>> regex.search(animaux)
<_sre.SRE_Match object at 0x7fefdaefe718>
>>> animaux = "singe tigre"
>>> regex.search(animaux)
Fonction findall()
Pour récupérer chaque zone, vous pouvez utiliser la fonction findall() qui renvoie une
liste des éléments en correspondance.
>>> regex = re.compile('[0-9]+\.[0-9]+')
>>> resultat = regex.findall("pi vaut
3.14 et e vaut 2.72")
>>> resultat
['3.14', '2.72']
>>> regex = re.compile('([0-9]+)\.([0-9]+)')
>>> resultat = regex.findall("pi vaut
3.14 et e vaut 2.72")
>>> resultat
[('3', '14'),
('2', '72')]
Fonction sub()
Enfin, la fonction sub() permet d'effectuer
des remplacements assez puissants. Par défaut la fonction sub(chaine1,chaine2) remplace toutes les occurrences trouvées par l'expression régulière
dans chaine2 par chaine1. Si vous souhaitez ne remplacer que les n premières
occurrences, utilisez l'argument count=n :
>>> regex.sub('quelque chose',"pi
vaut 3.14 et e vaut 2.72")
'pi vaut quelque chose et e vaut quelque chose'
>>> regex.sub('quelque chose',"pi
vaut 3.14 et e vaut 2.72", count=1)
'pi vaut quelque chose et e vaut 2.72'
Autres symboles qui ont une
signification:
(x|y) Indique un choix multiple type (ps|ump) équivaut à "ps" OU
"UMP"
\d le segment
est composé uniquement de chiffre, ce qui équivaut à [0-9].
\D le segment
n'est pas composé de chiffre, ce qui équivaut à [^0-9].
\s Un espace,
ce qui équivaut à [ \t\n\r\f\v].
\S Pas
d'espace, ce qui équivaut à [^ \t\n\r\f\v].
\w Présence
alphanumérique, ce qui équivaut à [a-zA-Z0-9_].
\W Pas de
présence alphanumérique [^a-zA-Z0-9_].
Exercice :
Validation d’une
adresse email avec la syntaxe :
Syntaxe :nom@site.type avec type composé de 2 a 4 caractères (.com,.fr,…)
Solution :
Re.findall(r’\w+@\w+.\w{2,4}’,’dan@tr.com’)