Expressions régulières,  Linux,  Programmation,  Python

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

Programmation, science de données et marketing

6 commentaires

  • 2Dchart92.Wordpress.com

    Hi there! I could have sworn I’ve been to this site before but after looking at a
    few of the posts I realized it’s new to me. Anyhow, I’m definitely pleased I came across it and I’ll be bookmarking
    it and checking back regularly!

  • http://www.zibenquan.org

    Hi I am so delighted I found your web site, I really found you by mistake, while I was researching on Aol for something
    else, Anyhow I am here now and would just
    like to say cheers for a remarkable post and a all round enjoyable blog (I also love the
    theme/design), I don’t have time to browse it all at
    the moment but I have bookmarked it and also added your RSS feeds, so when I have time I will
    be back to read a great deal more, Please do keep up the awesome
    work.

  • Studio Wonderlike

    I simply couldn’t leave your web site prior to suggesting that I extremely loved the usual information an individual supply to your guests?
    Is going to be back frequently to check out new posts

  • spinning seo

    I do accept as true with all the concepts you have presented on your post.

    They are really convincing and will definitely work. Nonetheless, the posts
    are very short for starters. Could you please extend them
    a little from subsequent time? Thank you for the post.