Voici un deuxième exemple d'utilisation d'expressions rationnelles, toujours tiré de dive into Python.
Les caractères romains sont au nombre de sept :
Quatre caractères commencent par 1 en écriture décimale (I, X, C et M), les trois autres par 5.
Les caractères romains servent à construire les chiffres romains, à partir des règles suivantes :
On souhaite vérifier qu’une chaîne de caractères correspond à un chiffre romain.
On commence par vérifier que l'utilisation du caractère des milliers M est valide, vu que les caractères romains s'utilisent du plus grand vers le plus petit :
>>> import re >>> motif = '^M?M?M?$'
Le motif précédent a trois parties :
search est la fonction de base du module re. Elle reçoit une expression régulière (un motif), et une chaîne de caractères.
Si la chaîne contient le motif, un objet SRE_Match est renvoyé, signalant que l'expression régulière est présente. Sinon, search ne renvoie rien...
>>> re.search(motif, '') <SRE_Match object at 0106F4A8> >>> re.search(motif, 'M') <SRE_Match object at 0106FB58> >>> re.search(motif, 'MM') <SRE_Match object at 0106C290> >>> re.search(motif, 'MMM') <SRE_Match object at 0106AA38> >>> re.search(motif, 'MMMM')
Les quatre premières chaînes sont reconnues, qui correspondent à 0, 1, 2 ou trois utilisation du caractère des milliers M. La dernière chaîne ne l'est pas : 4 M n'est pas acceptable
Nous verrons plus loin que, en cas de présence du motif, l'objet SRE_Match permettra de décrire précisément la correspondance.
Il est plus délicat d'exprimer le motif des centaines, vu que C n'est pas l'unique caractère utilisé :
Il y a donc quatre motifs possibles :
Qui peuvent se condenser en :
Le motif correspondant aux milliers et centaines est donc le suivant :
>>> import re >>> pattern = '^M?M?M?(CM|CD|D?C?C?C?)$'
Il utilise le tube | pour signifier «ou».
Vérifions que les motifs, sensés être reconnus, le sont bien...
>>> re.search(pattern, 'MCM') <SRE_Match object at 01070390> >>> re.search(pattern, 'MD') <SRE_Match object at 01073A50> >>> re.search(pattern, 'MMMCCC') <SRE_Match object at 010748A8> >>> re.search(pattern, 'MCMC') >>> re.search(pattern, '') <SRE_Match object at 01071D98>
Prendre en charge les dizaines.
Plutôt que de multiplier les ?, on peut utiliser la syntaxe {m,n}, qui signifie «de m à n fois le caractère précédent» :
>>> motif = '^M{0,3}$' >>> re.search(motif, 'M') <_sre.SRE_Match object at 0x008EEB48> >>> re.search(motif, 'MM') <_sre.SRE_Match object at 0x008EE090> >>> re.search(motif, 'MMM') <_sre.SRE_Match object at 0x008EEDA8> >>> re.search(motif, 'MMMM')
Tout se passe sans problème.
Notons que la syntaxe {m} signifie exactement m fois le motif précédent.
On souhaite dorénavant étendre notre expression rationnelle, pour prendre en compte les dizaines.
Cela se fait comme pour les centaines :
>>> motif = '^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})$' >>> re.search(motif, 'MCMXL') <_sre.SRE_Match object at 0x008EEB48> >>> re.search(motif, 'MCML') <_sre.SRE_Match object at 0x008EEB48> >>> re.search(motif, 'MCMLX') <_sre.SRE_Match object at 0x008EEB48> >>> re.search(motif, 'MCMLXXX') <_sre.SRE_Match object at 0x008EEB48> >>> re.search(motif, 'MCMLXXXX') >>>
Finir le motif, pour prendre en charge les unités (correction).