Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Licence CC BY-NC-ND Thierry Parmentelat & Arnaud Legout Inria - UCA

Nous vous proposons dans ce notebook quelques exercices sur les expressions régulières. Faisons quelques remarques avant de commencer :

Liens utiles

Pour travailler sur ces exercices, il pourra être profitable d’avoir sous la main :

Exercice - niveau intermédiaire (1)

Identificateurs Python

On vous demande d’écrire une expression régulière qui décrit les noms de variable en Python. Pour cet exercice on se concentre sur les caractères ASCII. On exclut donc les noms de variables qui pourraient contenir des caractères exotiques comme les caractères accentués ou autres lettres grecques.

Il s’agit donc de reconnaître toutes les chaînes qui commencent par une lettre ou un _, suivi de lettres, chiffres ou _.

# quelques exemples de résultat attendus
from corrections.regexp_pythonid import exo_pythonid
exo_pythonid.example()
Loading...
# à vous de jouer: écrivez ici
# sous forme de chaîne votre expression régulière

regexp_pythonid = r"votre_regexp"
# évaluez cette cellule pour valider votre code
exo_pythonid.correction(regexp_pythonid)
Loading...

Exercice - niveau intermédiaire (2)

Lignes avec nom et prénom

On veut reconnaître dans un fichier toutes les lignes qui contiennent un nom et un prénom.

from corrections.regexp_agenda import exo_agenda
exo_agenda.example()
The history saving thread hit an unexpected error (OperationalError('attempt to write a readonly database')).History will not be written to the database.
Loading...

Plus précisément, on cherche les chaînes qui :

On vous demande de construire une expression régulière qui définit les deux groupes nom et prenom, et qui rejette les lignes qui ne satisfont pas ces critères.

Dans la correction - et ce sera pareil pour tous les exercices de regexp où on demande des groupes - la correction affiche uniquement les groupes demandés; ici on va vous montrer les groupes nom et prenom; vous avez parfaitement le droit d’utiliser des groupes supplémentaires, nommés ou pas d’ailleurs, dans votre propre regexp.

# entrez votre regexp ici
# il faudra la faire terminer par \Z
# regardez ce qui se passe si vous ne le faites pas

regexp_agenda = r"votre regexp\Z"
# évaluez cette cellule pour valider votre code
exo_agenda.correction(regexp_agenda)
Loading...

Exercice - niveau intermédiaire (3)

Numéros de téléphone

Cette fois on veut reconnaître des numéros de téléphone français, qui peuvent être :

Dans tous les cas on veut trouver dans le groupe number les 9 chiffres vraiment significatifs, comme ceci :

from corrections.regexp_phone import exo_phone
exo_phone.example()
Loading...
# votre regexp
# à nouveau il faut terminer la regexp par \Z
regexp_phone = r"votre regexp\Z"
# évaluez cette cellule pour valider votre code
exo_phone.correction(regexp_phone)
Loading...

Exercice - niveau avancé

Vu comment sont conçus les exercices, vous ne pouvez pas passer à re.compile un drapeau comme re.IGNORECASE ou autre ; sachez cependant que vous pouvez embarquer ces drapeaux dans la regexp elle-même ; par exemple pour rendre la regexp insensible à la casse de caractères, au lieu d’appeler re.compile avec le flag re.I, vous pouvez utiliser (?i) comme ceci :

import re
# on peut embarquer les flags comme IGNORECASE
# directement dans la regexp
# c'est équivalent de faire ceci

re_obj = re.compile("abc", flags=re.IGNORECASE)
re_obj.match("ABC").group(0)
'ABC'
# ou cela

re.match("(?i)abc","ABC").group(0)
'ABC'
# les flags comme (?i) doivent apparaître
# en premier dans la regexp
re.match("abc(?i)","ABC").group(0)
---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
Cell In[13], line 3
      1 # les flags comme (?i) doivent apparaître
      2 # en premier dans la regexp
----> 3 re.match("abc(?i)","ABC").group(0)

File /usr/lib/python3.12/re/__init__.py:167, in match(pattern, string, flags)
    164 def match(pattern, string, flags=0):
    165     """Try to apply the pattern at the start of the string, returning
    166     a Match object, or None if no match was found."""
--> 167     return _compile(pattern, flags).match(string)

File /usr/lib/python3.12/re/__init__.py:307, in _compile(pattern, flags)
    301     import warnings
    302     warnings.warn("The re.TEMPLATE/re.T flag is deprecated "
    303             "as it is an undocumented flag "
    304             "without an obvious purpose. "
    305             "Don't use it.",
    306             DeprecationWarning)
--> 307 p = _compiler.compile(pattern, flags)
    308 if flags & DEBUG:
    309     return p

File /usr/lib/python3.12/re/_compiler.py:745, in compile(p, flags)
    743 if isstring(p):
    744     pattern = p
--> 745     p = _parser.parse(p, flags)
    746 else:
    747     pattern = None

File /usr/lib/python3.12/re/_parser.py:979, in parse(str, flags, state)
    976 state.flags = flags
    977 state.str = str
--> 979 p = _parse_sub(source, state, flags & SRE_FLAG_VERBOSE, 0)
    980 p.state.flags = fix_flags(str, p.state.flags)
    982 if source.next is not None:

File /usr/lib/python3.12/re/_parser.py:460, in _parse_sub(source, state, verbose, nested)
    458 start = source.tell()
    459 while True:
--> 460     itemsappend(_parse(source, state, verbose, nested + 1,
    461                        not nested and not items))
    462     if not sourcematch("|"):
    463         break

File /usr/lib/python3.12/re/_parser.py:840, in _parse(source, state, verbose, nested, first)
    838 if flags is None:  # global flags
    839     if not first or subpattern:
--> 840         raise source.error('global flags not at the start '
    841                            'of the expression',
    842                            source.tell() - start)
    843     verbose = state.flags & SRE_FLAG_VERBOSE
    844     continue

error: global flags not at the start of the expression at position 3

Pour plus de précisions sur ce trait, que nous avons laissé de côté dans le complément pour ne pas trop l’alourdir, voyez la documentation sur les expressions régulières et cherchez la première occurrence de iLmsux.

Décortiquer une URL

On vous demande d’écrire une expression régulière qui permette d’analyser des URLs.

Voici les conventions que nous avons adoptées pour l’exercice :

Enfin, vous devez définir les groupes proto, user, password, hostname, port et path qui sont utilisés pour vérifier votre résultat. Dans la case Résultat attendu, vous trouverez soit None si la regexp ne filtre pas l’intégralité de l’entrée, ou bien une liste ordonnée de tuples qui donnent la valeur de ces groupes ; vous n’avez rien à faire pour construire ces tuples, c’est l’exercice qui s’en occupe.

# exemples du résultat attendu
from corrections.regexp_url import exo_url
exo_url.example()
Loading...
# n'hésitez pas à construire votre regexp petit à petit

regexp_url = "votre_regexp"
exo_url.correction(regexp_url)
Loading...