mercredi 21 octobre 2015

sed utile

Et oui, c'est utile (sed utile)! La preuve par la suite.
Partant d'un fichier pdf, nous construisons chaque mois un fichier texte reprenant les dépenses liées à l’utilisation  d'une carte bancaire et ce en vue d'une importation dans une base de données.
Tout était OK jusqu'à ce que brusquement le fichier texte obtenu ne convienne plus alors que apparemment au niveau du fichier pdf rien n'était changé.
Ce fichier texte inadéquat se présentait comme suit:

blabla1 15,65
EUR
blabla2 58,49
EUR
blabla3 214,29
EUR
blabla4 1.028,56
EUR

La première anomalie (le nom de la devise sur une ligne à part) peut se résoudre facilement avec la commande sed:



Explications:
sed importe dans son espace de travail la première ligne du fichier cbxy avant d'exécuter le script, à savoir le texte entre apostrophes. Ce script comprend 2 commandes:

  1. N provoque l'importation de la ligne 2 dans l'espace de travail
  2. s/\n/ / remplace par un espace le caractère de fin de ligne (\n) qui sépare les deux lignes: elles sont concaténées.
La fin du script déclenche l'impression automatique de l'espace de travail puis sed passe à la lecture de la ligne suivante, c'est-à-dire la ligne 3 (blabla2).

Le problème serait donc résolu s'il n'y avait qu'une seule anomalie. Hélas une autre anomalie est apparue: la disparition du signe moins (-) devant les montants (alors que ce signe est bel et bien présent dans le fichier pdf).
De nouveau sed va nous aider:



L'option r enjoint à sed d'utiliser les expressions régulières étendues. L'option n désactive l'impression automatique de l'espace de travail, par contre le p qui se trouve à la fin du script provoque son impression à chaque substitution. De la sorte nous recevons en output seulement les lignes qui nous intéressent.
Dans la commande de substitution

s/ ([0-9]{1,3},[0-9]{2})$/ -\1/

le motif recherché se trouve en fin de ligne (symbole $). Il est constitué d'un espace suivi de 1 à 3 chiffres, une virgule puis encore 2 chiffres. Dans la chaîne de remplacement \1 désigne la partie de la chaîne trouvée correspondant à l'expression régulière qui est entre parenthèses. L'utilisation des parenthèses permet ainsi d'éviter que le signe moins ajouté soit suivi d'un espace.

La ligne blabla4 manque à l'appel. Elle peut être traitée comme ceci:


Cette fois la commande de substitution est:

s/[0-9]{1,3}\.[0-9]{3},[0-9]{2}$/-&/

La chaîne recherchée située en fin de ligne doit correspondre au motif suivant:
1 à 3 chiffres suivi d'un point, puis 3 chiffres une virgule et encore 2 chiffres (dans l’expression régulière le point est échappé ou sinon il correspondrait à n'importe quel caractère). Dans la chaîne de remplacement, & désigne la totalité de la chaîne trouvée.

Pour transformer cbxy tout en conservant les commandes à exécuter, nous créons le fichier cbxy.sed:


#!/bin/sed -rf
s/[0-9]{1,3}\.[0-9]{3},[0-9]{2}$/-&/
s/ ([0-9]{1,3},[0-9]{2})$/ -\1/
N
s/\n/ /

Nous le rendons exécutable avant utilisation:


Tout semble OK. On termine avec la commande:

[toto@rigel cbxy]$ ./cbxy.sed cbxy > cbxyok