AWK – remplacement de caractères et parser des fichiers

La commande awk permet d’effectuer des traitements sur des chaines de caractères ou des fichiers en se basant sur des modèles et un langage propre, ainsi que l’utilisation d’expressions rationnelles.

Premier exemple, parser une ligne contenant des termes séparés par un espace (tout se passe dans un terminal sous GNU/Linux of course) :
On charge une variable avec ces 3 mots :
[bash]ligne="mot1 mot2 mot3"[/bash]
Puis on veut extraire le premier mot :
[bash]echo $ligne|awk -F " " ‘{print $1}'[/bash]
ou extraire le premier et le troisieme :
[bash]echo $ligne|awk -F " " ‘{print $1 $3}'[/bash]

On notera qu’ici -F permet de définir le séparateur de champs, puis, la commande « print » permet d’afficher la valeur contenue dans le champs choisi (indexé de 1 à n). L’index « 0 » comme en bash, représente l’ensemble de la chaine originale passée en argument.

AWK permet également des traitements sur les chaines de caractères, afin par exemple d’opérer un remplacement basé sur un modèle.
On charge une variable avec une chaine :
[bash]ligne="le chien est noir,le chat est gris"[/bash]
Et on va changer la couleur du chien et ne garder que le chien :
[bash]echo $ligne|awk -F "," ‘{gsub("noir","blanc",$1);print $1}'[/bash]
Ceci va afficher « Le chien est blanc ». Comme vu plus haut, le -F permet de casser la chaine sur toutes les virgules rencontrées, chaque élément est accessible via l’index en variable ($1 ou $2 ici). Puis, la commande gsub (substitution) permet de remplacer toute valeur « noir » par « blanc », dans la variable $1 (soit la partie avant la virgule).

La commande gsub s’est donc appliquée à $1, l’instruction print est indépendante, on aurait pu taper:
[bash]echo $ligne|awk -F "," ‘{gsub("noir","blanc",$1);print $1","$2}'[/bash]
afin d’afficher la partie modifiée et la seconde non modifiée.

Jusqu’ici nous avons travaillé sur des variables, mais awk permet de travailler sur des fichiers pour un traitement rapide.
Prenons le fichier /etc/passwd qui contient des éléments de ce type : root:x:0:0:root:/root:/bin/bash

Nous souhaitons par exemple afficher une liste des utilisateurs existants, leur home, et le shell associé. On constate donc que le « : » peut être utilisé comme séparateur.
Nous allons donc afficher le listing voulu de la manière suivante (login => home => shell) :
[bash]awk -F "\:" ‘{print $1" => "$6" => "$7}’ /etc/passwd[/bash]

Dans ce dernier point, nous avons parsé directement un fichier, et affiché le résultat dans la console. Il est possible de renvoyer le résultat dans un fichier avec une simple redirection :
[bash]awk -F "\:" ‘{print $1" => "$6" => "$7}’ /etc/passwd > mon_listing.txt[/bash]

Vous pouvez utiliser différents caractères spéciaux codés de la manière suivante :
\\ Un antislash.

\b retour arriere (backspace).

\n nouvelle ligne.

\r retour chariot.

\t tabulation horizontale.

\v tabulation verticale.

De manière générale les caractères spéciaux (* % etc.) doivent être « échappés » par un antislash.

On peut également utiliser les expressions régulières (ou rationnelles) afin de définir un séparateur.
[bash]awk -F "[^a-z|^A-Z|^0-9|^–|^/|^,]" ‘{print $1" => "$2" => "$3" => "$4" => "$5" => "$6" => "$7}’ /etc/passwd[/bash]

Dans l’exemple ci dessus, on va lire le fichier /etc/passwd on utilisant comme séparateur de champs l’expression rationnelle suivante :
[bash][^a-z|^A-Z|^0-9|^–|^/|^,][/bash]

Celle ci signifie que sera considéré comme séparateur de champs tout caractère qui n’est pas alphanumérique en majuscule ou minuscule, et différent de -, de / et de ,.

Plus d’informations sur les expressions rationnelles : http://fr.wikipedia.org/wiki/Expression_rationnelle

Dernier exemple, on va passer une chaine en majuscule avec la fonction « toupper » (il existe aussi tolower pour l’inverse):
[bash]echo "Coucou comment ça va?"|awk ‘{print toupper($0)}'[/bash]

Pour plus d’informations, man awk

Loading

Tags: , , , , , , ,

mardi, octobre 26th, 2010 Bash, GNU - Linux, Technologie

2 Commentaires to AWK – remplacement de caractères et parser des fichiers

  • tresronours dit :

    A voir aussi, d’autres informations pratiques, dont une avec awk permettant d’utiliser les conditions dans AWk :
    http://indexatech.2y.net:8080/unix/fra/unx_pipes.html

    Avec la commande :
    Station% ls -l | awk ‘$5 > 10000 { print $9 }’ > MesGrosFichiers

    On a donc une utilisation intéressante de awk uniquement utilisé avec une condition pour l’affichage (extraction) d’un contenu.

  • tresronours dit :

    Voilà un petit script bash fait vite fait pour renommer des fichiers mp3 contenant des parenthèses et des majuscules pour qu’ils soient reconnus sur un ipod jailbreaké.

    En effet, « on » m’a posé cette problématique, avec un ipod touch (oui du logiciel propriétaire fermé, piouk) jailbreaké, utilisant le player « smusic pro » pour lire les mp3 directement depuis le système de fichier.

    Hors les mp3 de l’utilisateur contiennent des parenthèses et des majuscules, ce qui fait que « smusic pro » ne les voit pas dans les fichiers présents sur l’ipod.

    Voici le petit script bash proposé pour renommer les fichiers avant de les copier sur le pod (Sous GNU/Linux évidemment) :
    [bash]#!/bin/bash

    #Ce script va renommer tout le contenu mp3 du dossier en cours en virant les parentheses et tout passer en minuscules pour compat_ipod

    for i in `ls *.mp3 *.MP3 2>/dev/null`; do

    echo "Je traite : "$i;
    #$i contient le nom du fichier qui m’interesse dans le dossier en cours
    echo "Passage en minuscule : "
    montitre=`echo $i|awk ‘{print tolower($0)}’`
    echo ${montitre}
    echo "Suppression des parentheses : "
    #suppression des parenthese avec awk gsub
    echo ${montitre}|awk ‘{gsub("[\\(|\\)]","",$1);print $1 }’
    nouveautitre=`echo ${montitre}|awk ‘{gsub("[\\\(|\\\)]","",$1);print $1 }’`

    echo "Renommage du fichier $i en ${nouveautitre} : "
    if [ ! -z "${nouveautitre}" ]; then
    mv $i ${nouveautitre}
    #echo "renommage"
    fi
    done
    [/bash]

    Voilà, c’est juste pour l’aspect didactique :)

  • Ajouter un commentaire