24 septembre 2012

Eclater un fichier (de bordereaux) avec la commande awk

Il est fréquent qu'il faille découper un fichier en plusieurs morceaux (interfaces, éditions). Pour cela c'est la commande "grep" qui est la plus souvent utilisée.

Exemple : avec le fichier de bordereaux ${FIC} suivant,

000000000HRMYI11                                  *FZD00                       0HRMYI11
000000000HRMYI12                                  *FZD00                       0HRMYI12
000000000HRMYI21                                  *FZD00                       0HRMYI21
000000000HRMYI22                                  *FZD00                       0HRMYI22
000000000HRMYI31                                  *FZD00                       0HRMYI31
000000000HRMYI32                                  *FZD00                       0HRMYI32
000000000HRMYI41                                  *FZD00                       0HRMYI41


Si l'on souhaite éclater le fichier suivant suivant le code du répertoire réglementaire (YI1, YI2, ... en colonne 13 sur 3 caractères) il est nécessaire :
  • De lister les valeurs du code (découpage, tri et élimination des doublons) :
   cut -c13-15 ${FIC} | sort -u
  • De boucler pour chaque valeur de code
   while ... do ... done
  • D'extraire les bordereaux pour chacun des codes dans un fichier ${FIC}.${CODE}
   grep "^000000000HRM${CODE:-   }" ${FIC} > ${FIC}.${CODE}
        NB : ${CODE:-   } permet d'attribuer par défaut la valeur "   " à CODE

Soit :
rm -f  ${FIC}.* # Purge prealable
cut -c13-15 ${FIC} | sort -u | while read CODE
do
   grep "^000000000HRM${CODE:-   }" ${FIC} > ${FIC}.${CODE}
done

L'inconvénient est qu'il faut exécuter la commande "grep" autant de fois qu'il y a de valeur au critère d'éclatement. Quand le fichier est volumineux, le traitement peut être long (si un grep met 1 minutes, 10 greps prendront 10 minutes).

Une solution : la commande awk. Celle ci permet d'obtenir le même résultat en une passe :

rm -f  ${FIC}.* # Purge prealable
awk "{CODE=substr(\$0,13,3); print \$0 > \"$FIC.\"CODE }" ${FIC}

  • CODE=substr permet d'extraire les caractères 13 à 15 de chaque bordereaux et de les stocker dans la variable CODE,
  • print $0 écrit le bordereau,
  • > "$FIC."CODE redirige l'écriture dans des fichiers suffixés par CODE,
  • Tout est dans l'utilisation de quotes doubles pour que les variables Unix dans le script awk soient interprétées, et dans la mise en place des caractères "\" protégeant les champs et les quotes propres au "awk"...

1 commentaire: