👩‍🔬 En mars, soulignons le mois de l'histoire des femmes 🙋‍♀️

Potion Bottle Icon Manuel d'alchimie du code Potion Bottle Icon

Manipulation de fichiers texte avec sed, AWK et grep

966 mots - Temps de lecture estimé: 5 minutes

Le but de cette mini-formation est d'introduire trois outils courants dans le monde POSIX pour traiter des fichiers texte. Ces outils sont disponibles sur toutes les distributions Linux, ainsi que sur MacOS et dans Windows Subsystem for Linux.

🌘 Introduction

🌘 sed

La syntaxe la plus utilisée est de la forme suivante :

sed -e 's/Ancien/Nouveau/g' nomFichierEntrée > nomFichierSortie

L'expression est composée de commandes (s pour substitution), de deux expressions régulières et de drapeaux (g pour global). La deuxième expression peut aussi inclure des références vers les groupes de la première expression.

Il est possible d'éditer sur place et de créer une copie de sauvegarde

sed -ibak 's/Ancien/Nouveau/g' nomFichierEntrée

🌘 awk

AWK est un langage de programmation orienté par les données. En fait, ce sont les données qu'on lui passe en entrée qui déterminent le flux d'exécution. Il sert entre autres à produire du code automatiquement selon un fichier de paramètres.

La version la plus utilisée d’AWK est GNU AWK, appelé avec la commande gawk.

Un programme prend la forme suivante :

awk [options] [programme] [fichier]

Les principales options utilisées sont :

Le programme a la structure suivante : 'motif{action}motif{action}'

Le motif est soit une expression régulière, une variable ou un motif spécial : BEGIN ou END

🌘 grep

La commande grep provient de global regular expression print et permet de rechercher les lignes qui contiennent une certaine expression régulière dans un texte, un fichier ou un répertoire de fichiers.
Utilisé en combinaison avec d'autres commandes, c'est le principal outil de recherche des systèmes POSIX.

La syntaxe de grep est :

grep 'expression' fichiers

🌘 Exemples de manipulation de fichiers texte

🌘 Données

Nous travaillerons sur un extrait de texte libre : Amusements in Mathematics par Henry Ernest Dudeney Il s'agit d'un recueil de problèmes mathématiques

wget https://ia800300.us.archive.org/27/items/amusementsinmath16713gut/16713.txt

Voici un aperçu du contenu, extrait avec ce programme que nous étudierons

cat 16713.txt | \
  gawk 'BEGIN{count=1}/^9\.\-\-/{print "Extrait : "count" ";flag=1;count++;next}/^10\.\-\-/{flag=0}flag{print NR": "$0}' - | \
  grep '^[Extrait|0-9]\+ :\s\w\+' | \
  sed -E 's/L([0-9]*.?[0-9]+)/\1$/g'
Extrait : 1
399 : A man recently bought two aeroplanes, but afterwards found that they
400: would not answer the purpose for which he wanted them. So he sold them
401: for 600$ each, making a loss of 20 per cent. on one machine and a profit
402: of 20 per cent. on the other. Did he make a profit on the whole
403: transaction, or a  loss ? And how  much ? Extrait : 2
11569 : The man must have paid 500$ and 750$ for the two machines, making
11570: together 1,250$; but as he sold them for only 1,200$, he lost 50$ by the
11571: transaction.

🌘 AWK

Explorons la première section de la commande :

gawk 'BEGIN{count=1}/^9\.\-\-/{print "Extrait : "count" ";flag=1;count++;next}/^10\.\-\-/{flag=0}flag{print NR" : "$0}' -

Le programme lié au motif BEGIN est exécuté avant la lecture du fichier en entrée.

Ensuite, le programme parcourt le fichier ligne par ligne jusqu'à ce qu'il rencontre une des situations suivantes :

À ce moment, il exécutera le code associé à chacune d'elles. Dans le premier cas, il imprimera le numéro de l'extrait print "Extrait : "count" ", mettra l'indicateur flag=1 et incrémentera le compteur count++.

Pendant que la variable flag vaut 1, les lignes sont imprimées, incluant le numéro de la ligne au début, représenté par la variable NR.

Lorsque la deuxième expression est rencontrée, le flag reprend la valeur 0 et les lignes cessent d'être imprimées. Ce programme permet donc d'extraire tous les blocs de texte inclus entre des lignes commençant par 9.-- et 10.--. Dans notre cas, il s'agit du problème # 9 et de sa solution.

La sortie obtenue est la suivante :

Extrait : 1
398 :
399 : A man recently bought two aeroplanes, but afterwards found that they
400: would not answer the purpose for which he wanted them. So he sold them
401: for L600 each, making a loss of 20 per cent. on one machine and a profit
402: of 20 per cent. on the other. Did he make a profit on the whole
403: transaction, or a  loss ? And how  much ? 404:
405: Extrait : 2
11568 :
11569 : The man must have paid L500 and L750 for the two machines, making
11570: together L1,250; but as he sold them for only L1,200, he lost L50 by the
11571: transaction.
11572:
11573:

🌘 grep

Explorons maintenant la deuxième expression :

grep '^[Extrait|0-9]\+:\s\w\+'

Cette expression sert à conserver les lignes qui ne sont pas vides, c'est-à-dire contenant au moins un mot \w+ après le numéro de ligne ou le mont Extrait, et la séquence : \s . C'est donc un filtre sur les lignes qui nous permet d'obtenir :

Extrait : 1
399 : A man recently bought two aeroplanes, but afterwards found that they
400: would not answer the purpose for which he wanted them. So he sold them
401: for L600 each, making a loss of 20 per cent. on one machine and a profit
402: of 20 per cent. on the other. Did he make a profit on the whole
403: transaction, or a  loss ? And how  much ? Extrait : 2
11569 : The man must have paid L500 and L750 for the two machines, making
11570: together L1,250; but as he sold them for only L1,200, he lost L50 by the
11571: transaction.

Lorsque la commande est exécutée dans un terminal supportant les couleurs, les chaines de caractères correspondant à l'expression recherchée seront en couleur.

Exemple d'utilisation de AWK et de grep pour faire une manipulation de fichier texte, avec de la couleur

🌘 sed

Explorons enfin la dernière commande :

sed -E 's/L([0-9]*.?[0-9]+)/\1$/g'

Nous voulons remplacer les montants en livres pour des dollars.
Cette commande recherche un nombre décimal précédé de L. Nous voulons le remplacer par le même nombre, suivi d'un symbole de dollar $.
Le groupe que l'on désire identifier et conserver est placé entre parenthèses. C'est un groupe de capture. On peut ensuite rappeler ces groupes dans la substitution à l'aide des marqueurs de groupes \1... \9.

On obtient enfin

Extrait : 1
399 : A man recently bought two aeroplanes, but afterwards found that they
400: would not answer the purpose for which he wanted them. So he sold them
401: for 600$ each, making a loss of 20 per cent. on one machine and a profit
402: of 20 per cent. on the other. Did he make a profit on the whole
403: transaction, or a  loss ? And how  much ? Extrait : 2
11569 : The man must have paid 500$ and 750$ for the two machines, making
11570: together 1,250$; but as he sold them for only 1,200$, he lost 50$ by the
11571: transaction.

🌘 Articles connexes

Abonne-toi au flux RSS pour ne rien manquer.

Étiquettes