.. _2020regexrst: ============================= Tech - expressions régulières ============================= .. only:: html **Links:** :download:`notebook <2020_regex.ipynb>`, :downloadlink:`html <2020_regex2html.html>`, :download:`python <2020_regex.py>`, :downloadlink:`slides <2020_regex.slides.html>`, :githublink:`GitHub|_doc/notebooks/td1a_home/2020_regex.ipynb|*` Les `expressions régulières `__ sont utilisées pour rechercher des motifs dans un texte tel que des mots, des dates, des nombres… .. code:: ipython3 from jyquickhelper import add_notebook_menu add_notebook_menu() .. contents:: :local: Enoncé ------ Le texte suivant est un poème d’Arthur Rimbaud, Les Voyelles. On veut en extraire tous les mots. .. code:: ipython3 poeme = """ A noir, E blanc, I rouge, U vert, O bleu, voyelles, Je dirai quelque jour vos naissances latentes. A, noir corset velu des mouches éclatantes Qui bombillent autour des puanteurs cruelles, Golfe d'ombre; E, candeur des vapeurs et des tentes, Lance des glaciers fiers, rois blancs, frissons d'ombelles; I, pourpres, sang craché, rire des lèvres belles Dans la colère ou les ivresses pénitentes; U, cycles, vibrements divins des mers virides, Paix des pâtis semés d'animaux, paix des rides Que l'alchimie imprime aux grands fronts studieux; O, suprême clairon plein de strideurs étranges, Silences traversés des Mondes et des Anges: —O l'Oméga, rayon violet de Ses Yeux! """ Exercice 1 : utiliser les expression régulières pour extraire tous les mots ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ En python, il faut utiliser le module `re `__. Il faudra lire le paragraphe sur la syntaxe `Regular Expression Syntax `__. Autres lectures : `Expressions régulières `__. .. code:: ipython3 def extract_words(text): # utiliser les exrp pass extract_words(poeme) Exercice 2 : utiliser les expression régulières pour extraire tous les mots se terminant par la lettre s ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Exercice 3 : utiliser les expression régulières pour remplacer tous les “de” en 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Les fonctions `finditer `__ ou `sub `__ pourraient vous être utile. Exercice 4 : utiliser les expression régulières pour extraire les lignes des rimes en ``elle`` ou ``elles`` ou ``aile`` ou ``ailes`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ La fonction `finditer `__ pourrait vous être utile. Réponses -------- Exercice 1 : utiliser les expression régulières pour extraire tous les mots ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Les accents sont traités comme des lettres différentes par les expressions régulières. On peut soit les garder, soit les remplacer. Pour ce faire, on peut lire `What is the best way to remove accents (normalize) in a Python unicode string? `__. .. code:: ipython3 import unicodedata def strip_accents(s): return ''.join(c for c in unicodedata.normalize('NFD', s) if unicodedata.category(c) != 'Mn') strip_accents('têtu') .. parsed-literal:: 'tetu' .. code:: ipython3 import re def extract_words(text): text_sans_accent = strip_accents(text) return re.findall('[A-Za-z]+', text_sans_accent) mots = extract_words(poeme) mots[:5] .. parsed-literal:: ['A', 'noir', 'E', 'blanc', 'I'] Exercice 2 : utiliser les expression régulières pour extraire tous les mots se terminant par la lettre s ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ On modifie le motif pour qu’il se termine par la lettre *s*. Le caractère ``\b`` est utilisé pour signifier que cette lettre ne peut se trouver qu’à la fin d’un mot. .. code:: ipython3 def extract_words_lettre(text, lettre='s'): text_sans_accent = strip_accents(text) return re.findall('[A-Za-z]+[' + lettre + ']\\b', text_sans_accent) mots = extract_words_lettre(poeme, 'se') mots[:5] .. parsed-literal:: ['rouge', 'voyelles', 'Je', 'quelque', 'vos'] Exercice 3 : utiliser les expression régulières pour remplacer tous les “de” en 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code:: ipython3 re.sub("de\\b", "2", poeme) .. parsed-literal:: "\nA noir, E blanc, I rouge, U vert, O bleu, voyelles,\nJe dirai quelque jour vos naissances latentes.\nA, noir corset velu des mouches éclatantes\nQui bombillent autour des puanteurs cruelles,\n\nGolfe d'ombre; E, candeur des vapeurs et des tentes,\nLance des glaciers fiers, rois blancs, frissons d'ombelles;\nI, pourpres, sang craché, rire des lèvres belles\nDans la colère ou les ivresses pénitentes;\n\nU, cycles, vibrements divins des mers virides,\nPaix des pâtis semés d'animaux, paix des rides\nQue l'alchimie imprime aux grands fronts studieux;\n\nO, suprême clairon plein 2 strideurs étranges,\nSilences traversés des Mondes et des Anges:\n—O l'Oméga, rayon violet 2 Ses Yeux!\n" Exercice 4 : utiliser les expression régulières pour extraire les lignes des rimes en ``elle`` ou ``elles`` ou ``aile`` ou ``ailes`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Un petit essai avant la solution. .. code:: ipython3 re.findall("(((aile)|(elle))s?\\b)", poeme) .. parsed-literal:: [('elles', 'elle', '', 'elle'), ('elles', 'elle', '', 'elle'), ('elles', 'elle', '', 'elle'), ('elles', 'elle', '', 'elle')] Un autre pour se convaincre… .. code:: ipython3 for m in re.finditer("(((aile)|(elle))s?\\b)", poeme): print('%02d-%02d: %s' % ( m.start(), m.end(), m.group(0))) .. parsed-literal:: 46-51: elles 182-187: elles 296-301: elles 346-351: elles On mélange. On découpe en ligne d’abord, et on applique le même traitement sur chaque ligne. .. code:: ipython3 for i, ligne in enumerate(poeme.split('\n')): for m in re.finditer("(((aile)|(elle))s?\\b)", ligne): print('% 2d: %02d-%02d/%02d: %s' % ( i + 1, m.start(), m.end(), len(ligne), ligne)) .. parsed-literal:: 2: 45-50/51: A noir, E blanc, I rouge, U vert, O bleu, voyelles, 5: 39-44/45: Qui bombillent autour des puanteurs cruelles, 8: 53-58/59: Lance des glaciers fiers, rois blancs, frissons d'ombelles; 9: 43-48/48: I, pourpres, sang craché, rire des lèvres belles Il ne resterait plus qu’à vérifier que la rime trouvée, le motif, se trouve à la fin de la ligne.