You are here: Sommaire > Plongez au coeur de Python > Expressions régulières > Etude de cas : reconnaissance de numéros de téléphone | << >> | ||||
Plongez au coeur de PythonDe débutant à expert |
Jusqu'ici nous nous sommes concentrés sur la reconnaissance de motifs complets, le motif est reconnu ou non. Mais les expressions régulières sont beaucoup plus puissantes que cela. Lorsqu'une expression régulière reconnaît un motif, nous pouvons sélectionner certaines parties du motif. Nous pouvons savoir ce qui a été reconnu et à quel endroit.
Cet exemple est tiré d'un autre problème réel que j'ai eu au cours de mon travail précédent. Le problème : la reconnaissance de numéros de téléphone au Etats-Unis. Le client voulait que la saisie se fasse librement (dans un champ unique), mais voulait stocker le code régional, l'indicatif, le numéro et une extension optionnelle séparément dans la base de données. Je parcourais le Web et trouvais de nombreux exemples d'expressions régulières qui avaient pour but de faire cela, mais aucune n'était assez souple.
Voici les numéros de téléphone qu'il fallait que j'accepte :
Quelle diversité ! Dans chacun de ces cas, je devais savoir que le code régional était 800, l'indicatif 555 et le reste du numéro 1212. Pour les numéros avec extension, je devais savoir que celle-ci était 1234.
Nous allons développer une solution pour la reconnaissance des numéros de téléphone. Cet exemple montre la première étape.
>>> phonePattern = re.compile(r'^(\d{3})-(\d{3})-(\d{4})$')>>> phonePattern.search('800-555-1212').groups()
('800', '555', '1212') >>> phonePattern.search('800-555-1212-1234')
>>>
![]() |
Lisez toujours les expressions régulières de la gauche vers la droite. Celle-ci reconnaît le début de la chaîne, puis (\d{3}). Que veut dire ce \d{3}? Le {3} signifie «reconnaître exactement trois chiffres», c'est une variante de la syntaxe {n,m} que nous avons vu plus haut. \d signifie «n'importe quel chiffre» (de 0 à 9). En le mettant entre parenthèses, nous disons «reconnais exactement trois chiffres, puis identifie-les comme un groupe que je peux rappeler plus tard». Ensuite, le motif reconnaît un tiret, puis un autre groupe de trois chiffres, un autre tiret, un groupe de quatre chiffres et la fin de la chaîne. |
![]() |
Pour accéder aux groupes que l'expression régulière à identifiés, utilisez la méthode groups() de l'objet que la fonction search retourne. Elle retournera un tuple du nombre de groupes définis dans l'expression régulières. Dans ce cas, nous avons défini trois groupes, deux de trois chiffres et un de quatre. |
![]() |
Cette expression régulière n'est pas la réponse finale car elle ne prend pas en compte les numéros de téléphone avec une extension à la fin. Pour cela, nous allons devoir la modifier. |
>>> phonePattern = re.compile(r'^(\d{3})-(\d{3})-(\d{4})-(\d+)$')>>> phonePattern.search('800-555-1212-1234').groups()
('800', '555', '1212', '1234') >>> phonePattern.search('800 555 1212 1234')
>>> >>> phonePattern.search('800-555-1212')
>>>
L'exemple suivant montre l'expression régulière qui reconnaît les séparateurs entre les différentes parties d'un numéro de téléphone.
>>> phonePattern = re.compile(r'^(\d{3})\D+(\d{3})\D+(\d{4})\D+(\d+)$')>>> phonePattern.search('800 555 1212 1234').groups()
('800', '555', '1212', '1234') >>> phonePattern.search('800-555-1212-1234').groups()
('800', '555', '1212', '1234') >>> phonePattern.search('80055512121234')
>>> >>> phonePattern.search('800-555-1212')
>>>
L'exemple suivant montre l'expression régulière qui reconnaît les numéros de téléphone sans séparateurs.
>>> phonePattern = re.compile(r'^(\d{3})\D*(\d{3})\D*(\d{4})\D*(\d*)$')>>> phonePattern.search('80055512121234').groups()
('800', '555', '1212', '1234') >>> phonePattern.search('800.555.1212 x1234').groups()
('800', '555', '1212', '1234') >>> phonePattern.search('800-555-1212').groups()
('800', '555', '1212', '') >>> phonePattern.search('(800)5551212 x1234')
>>>
L'exemple suivant montre comment prendre en compte les caractères au début des numéros de téléphone.
>>> phonePattern = re.compile(r'^\D*(\d{3})\D*(\d{3})\D*(\d{4})\D*(\d*)$')>>> phonePattern.search('(800)5551212 ext. 1234').groups()
('800', '555', '1212', '1234') >>> phonePattern.search('800-555-1212').groups()
('800', '555', '1212', '') >>> phonePattern.search('work 1-(800) 555.1212 #1234')
>>>
Faisons le point. Jusqu'à présent, nos expressions régulières commençaient toujours la reconnaissance en début de chaîne, mais maintenant nous voyons qu'il peut y avoir un nombre indeterminé de caractères à ignorer en début de chaîne. Au lieu d'essayer de les identifier pour les sauter, essayons une approche différente : ne pas reconnaître explicitemment le début de la chaîne. C'est ce que nous verrons dans l'exemple suivant.
>>> phonePattern = re.compile(r'(\d{3})\D*(\d{3})\D*(\d{4})\D*(\d*)$')>>> phonePattern.search('work 1-(800) 555.1212 #1234').groups()
('800', '555', '1212', '1234') >>> phonePattern.search('800-555-1212')
('800', '555', '1212', '') >>> phonePattern.search('80055512121234')
('800', '555', '1212', '1234')
Vous avez pu voir comment les expressions régulières peuvent rapidemment échapper à tout contrôle. Parcourez les différentes versions de notre expression régulière, pouvez-vous dire quelles différences les séparent ?
Tant que nous comprenons encore la version finale (et c'est bien la version finale, si vous découvrez un cas qu'elle n'est pas capable de traiter, je ne veux pas en entendre parler), écrivons-la sous la forme d'une expression régulière détaillée avant d'oublier les choix que nous avons fait.
>>> phonePattern = re.compile(r''' # don't match beginning of string, number can start anywhere (\d{3}) # area code is 3 digits (e.g. '800') \D* # optional separator is any number of non-digits (\d{3}) # trunk is 3 digits (e.g. '555') \D* # optional separator (\d{4}) # rest of number is 4 digits (e.g. '1212') \D* # optional separator (\d*) # extension is optional and can be any number of digits $ # end of string ''', re.VERBOSE) >>> phonePattern.search('work 1-(800) 555.1212 #1234').groups()('800', '555', '1212', '1234') >>> phonePattern.search('800-555-1212')
('800', '555', '1212', '')
<< Expressions régulières détaillées |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
Résumé >> |