Regex 2e partie: lire un fichier et écrire à un fichier

Dans cette deuxième partie, je vais montrer comment appliquer un regex à un fichier au complet  et envoyer les résultats à un autre fichier. Le code pour cet article se trouve sur Git à https://github.com/srqty/messe_du_jour.

Sed

Commençons avec sed dans linux. J’ai écrit un script qui contient un regex. J’applique celui-ci à un fichier puis les résultats sont envoyés à un autre fichier. Voici  le script:

#script pour ajouter le jour de la semaine aux lecture des messes du jour

#exectuer dans bash: sed -f script_messe_lectures.sed fichier_à_modifier.html >> fichier_de_sortie.html

s/[> ]1 décembre 2018\|[> ]8 décembre 2018\|[> ]15 décembre 2018\|[> ]22 décembre 2018\|[> ]29 décembre 2018/samedi&/g

s/[> ]2 décembre 2018\|[> ]9 décembre 2018\|[> ]16 décembre 2018\|[> ]23 décembre 2018\|[> ]30 décembre 2018/dimanche&/g

s/[> ]3 décembre 2018\|[> ]10 décembre 2018\|[> ]17 décembre 2018\|[> ]24 décembre 2018\|[> ]31 décembre 2018/lundi&/g

s/[> ]4 décembre 2018\|[> ]11 décembre 2018\|[> ]18 décembre 2018\|[> ]25 décembre 2018/mardi&/g

s/[> ]5 décembre 2018\|[> ]12 décembre 2018\|[> ]19 décembre 2018\|[> ]26 décembre 2018/mercredi&/g

s/[> ]6 décembre 2018\|[> ]13 décembre 2018\|[> ]20 décembre 2018\|[> ]27 décembre 2018/jeudi&/g

s/[> ]7 décembre 2018\|[> ]14 décembre 2018\|[> ]21 décembre 2018\|[> ]28 décembre 2018/vendredi&/g

Dans le terminal, je tape «sed -f script_messe_lectures.sed» qui est le nom du fichier qui contient le script. Puis, j’écris suivi le fichier à lire et le fichier à écrire. Les «>>« indique le fichier de sortie qui, dans ce cas, doit être dans le même répertoire que le script.  

Notez que c’est la même expression régulière que dans la première partie. J’aime bien écrire un script, car je n’ai pas besoin de taper toutes les expressions régulières une à la fois dans le terminal.

Python

Voici la même expression régulière dans python:

import re

pattern1 = re.compile(r'([> ]1 décembre 2018|[> ]8 décembre 2018|[> ]15 décembre 2018|[> ]22 décembre 2018|[> ]29 décembre 2018)’)
pattern2 = re.compile(r'([> ]2 décembre 2018|[> ]9 décembre 2018|[> ]16 décembre 2018|[> ]23 décembre 2018|[> ]30 décembre 2018)’)
pattern3 = re.compile(r'([> ]3 décembre 2018|[> ]10 décembre 2018|[> ]17 décembre 2018|[> ]24 décembre 2018|[> ]31 décembre 2018)’)
pattern4 = re.compile(r'([> ]4 décembre 2018|[> ]11 décembre 2018|[> ]18 décembre 2018|[> ]25 décembre 2018)’)
pattern5 = re.compile(r'([> ]5 décembre 2018|[> ]12 décembre 2018|[> ]19 décembre 2018|[> ]26 décembre 2018)’)
pattern6 = re.compile(r'([> ]6 décembre 2018|[> ]13 décembre 2018|[> ]20 décembre 2018|[> ]27 décembre 2018)’)
pattern7 = re.compile(r'([> ]7 décembre 2018|[> ]14 décembre 2018|[> ]21 décembre 2018|[> ]28 décembre 2018)’)

with open(‘premier_décembre.txt’, ‘r’) as lf:
#Lire le contenu du fichier
    lf_contents = lf.read()
    remplacer1 = pattern1.sub(r’ samedi\1′, lf_contents)
    remplacer2 = pattern2.sub(r’ dimanche\1′, remplacer1)
    remplacer3 = pattern3.sub(r’ lundi\1′, remplacer2)
    remplacer4 = pattern4.sub(r’ mardi\1′, remplacer3)
    remplacer5 = pattern5.sub(r’ mercredi\1′, remplacer4)
    remplacer6 = pattern6.sub(r’ jeudi\1′, remplacer5)
    remplacer7 = pattern7.sub(r’ vendredi\1′, remplacer6)
    print(remplacer7, end= »)

    with open(‘outfile’, ‘w’) as ef:
         ef.write(remplacer7)

Je ne répéterai pas ce qui était écrit dans la première partie sur les regex.  Bien sur, il faut importer le module re avec la déclaration «import re».

Il a des points importants sur comment lire un fichier dans python. Corey Schafer l’explique bien dans un tutoriel sur Youtube qui s’intitule «Python Tutorial: File Objects – Reading and Writing to Files»1

Commençons par la ligne «with open(‘premier_décembre.txt’, ‘r’) as lf:» Le «with» indique à python de s’occuper de la fermeture du fichier. Cette déclaration agit comme un gestionnaire de contexte pour encadrer l’ouverture et la fermeture du fichier. Une fois qu’on sort du bloc de code, le gestionnaire de contexte va automatiquement fermer le fichier ‘premier_décembre.txt’ qui est le fichier qu’on veut lire. Avec le «with» le gestionnaire de contexte va aussi s’occuper des exceptions. Celui-ci doit déjà exister dans le répertoire. Le ‘r’ indique que le fichier est en mode lecture. Autrement dit, je peux lire le fichier, mais je ne peux le modifier.

«lf» est la variable qui contient le fichier «premier_décembre.txt». lf.read() est une méthode qui lit l’objet «lf». Elle lit tout le contenu du fichier. Notez que celle-ci ne lit pas le fichier «premier_décembre.txt» mais l’objet lf, c’est-à-dire une variable qui contient le fichier.

Supposons que «premier_décembre.txt» était très gros et que je ne voulais pas le lire au complet pour économiser le mémoire. Dans ce cas, j’utiliserai une boucle «for» pour lire le fichier une ligne à la fois. Schafer l’explique bien dans sa vidéo.

Comme mentionné dans la première partie, le sub() méthode de regex remplace le contenu trouvé par re.compile(). Dans ce cas, sub() a besoin du texte à ajouter et l’objet sur lequel la méthode sub() doit s’appliquer. Dans ce cas, «lf_contents», «remplacer1», «remplacer2», etc.  

Cela peut sembler évident. Mais j’ai fait l’erreur de mettre «lf_contents» partout dans les sub() au lieu de mettre «remplacer1», «remplacer2», etc. Le résultat? Rendu à «print(remplacer7, end= »)» seulement le dernier sub() s’affichait. C’est-à-dire, vendredi s’affichait mais pas les autres jours de la semaine. Pourquoi? Parce que le fichier «premier_décembre.txt» est en mode lecture ‘r’ seulement. Il ne peut être modifié. La méthode lf.read() lit l’object ‘lf’, mais celle-ci ne le modifie pas. En conséquence, la variable «lf_contents» ne peut être modifiée. Pour additionner les changements consécutifs, il me faut utiliser «remplacer1», 2, 3 etc dans les méthodes sub().

with open(‘outfile’, ‘w’) as ef:

Remarquons que cette ligne est mise en alinéa qui indique que ce code s’exécute avant que le fichier «premier_décembre.txt» soit fermé. Si le fichier «remplacer7» était très gros, je me servirais d’une boucle ‘for’ pour écrire une ligne à la fois. Ainsi, je réduirai l’usage de la mémoire.  

Voici ce que j’ai écrit au début:

with open(‘outfile’, ‘w’) as ef:
ef.write(remplacer7)

Cela a donné l’erreur suivante: «attributeerror-str-object-has-no-attribute-write». De prime abord, le code a du sens, car je veux écrire la variable «remplacer7»  au fichier outfile. J’ai trouvé la solution de l’erreur ici. 2 Il y a une bonne explication sur Youtube sur une vidéo qui s’intitule «Python TypeError: ‘str’ object does not support item assignment».

Voici l’explication: en python, on ne peut modifier un objet string (str). On peut le remplacer, mais on ne peut le modifier. Comme j’ai mentionné ci-haut en parlant de «lf», «ef» est la variable qui va envoyer le texte dans «remplacer7» au fichier «outfile». On peut appliquer la méthode write() à l’objet «ef». Il est donc légitime d’écrire ef.write(). Bien sur, je veux écrire le contenu de la variable «remplacer7» à l’objet (variable) ‘ef’. Il est donc légitime d’écrire «ef.write(remplacer7)».

Il y a une autre erreur dans la ligne: «remplacer7.write(outfile)». ‘outfile’ est un fichier texte, pas un variable. En fait, le variable «outfile» n’existe pas, car elle n’est jamais déclarée. En conséquence, je ne peux écrire la variable «outfile» dans cette ligne de code.

Ensuite, supposons que j’écris la ligne «remplacer7.write(‘outfile’)» qui va mettre le texte «outfile». Donc, le problème de variable «outfile» est réglé. Cependant, je vais toujours avoir l’erreur «attributeerror-str-object-has-no-attribute-write». Pourquoi, parce que «remplacer7» est une variable du type «str» et on ne peut modifier un objet du type «str».

En comparaison, je peux écrire «ef.write(‘outfile’)». Le contenu du fichier «outfile» va contenir le mot «outfile».

En conclusion, afin de travailler avec un fichier texte, il faut le mettre dans une variable. Voilà pourquoi on écrit «with open(‘nom_de_fichier, ‘r’, ‘a’, ‘w’) etc as ‘lf’, ‘ef»’ etc.

  1. «Python Tutorial: File Objects – Reading and Writing to Files» de Corey SCHAFER.
  2. https://stackoverflow.com/questions/18703525/attributeerror-str-object-has-no-attribute-write

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *