Command line Tips : passage de variable dans awk

But : Dans un fichier orga­ni­sé en colonnes, nous allons extraire les lignes conte­nant un mot (don­né en argu­ment) dans une colonne fixée à l'avance (1ère colonne).

Pré­re­quis : Connaître un peu le shell (pour l'exercice).

Dif­fi­cul­té : 2/​5 (Facile)

Exer­cice : Pour agré­men­ter la note, on extrai­ra dans quatre fichiers dis­tincts les lignes conte­nant les quatre mots les plus repré­sen­tés du fichier PDB ci-des­sous (un mot, un fichier). On pour­ra nom­mer les fichiers sous la forme "mot.txt".

PDB 6CSC

Dans une note récente, Leo_​01 nous détaillait plu­sieurs moyens d'extraire des colonnes d'un fichier. Je vous encou­rage à lire sa note (sur­tout si vous ne connais­sez pas awk).

awk est un inter­pré­teur et un lan­gage qui per­met d'appliquer un script à des fichiers texte plu­tôt orga­ni­sés en colonnes. Très pra­tique pour des fichiers de tailles rai­son­nables, il ne faut pas trop espé­rer trai­ter plu­sieurs mil­lions de lignes sans un peu d'attente (variable sui­vant la machine bien sûr). Il existe dif­fé­rentes ver­sions de awk, gawk, mawk et nawk (liste pas for­cé­ment exhaus­tive), mais toutes ses ver­sions étant POSIX, elles devraient être dis­po­nibles sur tout sys­tème POSIX et se com­por­ter de manière iden­tique.
La ligne de com­mande clas­sique tel que décrite par le man prend la forme sui­vante :

awk [options] 'script' file(s)

ou

awk [options] -f script.file file(s)

En général, j'utilise la première forme de ligne de commande. La deuxième peut avoir un intérêt si on veut générer le script de manière "dynamique" ou pour une question de lisibilité.
Parmi les options, la plus importante est probablement -F permettant d'indiquer le séparateur de champs mais celle qui va nous intéresser aujourd'hui est -v pour variable; extrait du man:

-v var=value assigns value to program variable var.

Exemple sans fichier d'entrée :

$ awk -v var=3 'BEGIN{print var;}'
3

Ici, on notera l'utilisation du mot clef "BEGIN" qui regroupe des instructions qui ne seront exécutées qu'une seule fois avant la lecture du fichier.
La structure d'un script awk prend la forme d'un bloc BEGIN{} (optionel), d'un bloc (optionel) sans étiquette simplement délimité par {} qui sera appliqué à chaque ligne du fichier et pour finir d'un bloc END{} (optionel) dont les instructions ne seront éxécutées qu'une seule fois après la fin de la lecture du fichier. L'interet des ces blocs se trouve par exemple pour calculer la moyenne d'une colonne. On initialiserait une variable dans un BEGIN, on sommerait les valeurs dans le bloc {} puis on afficherait la moyenne dans le bloc END.
Anecdote : le script le plus complet qui ne ferait rien serait donc 'BEGIN{}{}END{}'.
Note : on peut passer plusieurs variables en répétant l'option "-v".

Nous pouvons maintenant répondre à la question de départ. Nous allons extraire les lignes dont la première colonne contient le tag COMPND du fichier PDB.

$ awk -v k="COMPND" '{if ($1==k){print $0;}}' 6CSC.pdb
COMPND MOL_ID: 1;
COMPND 2 MOLECULE: CITRATE SYNTHASE;
COMPND 3 CHAIN: A, B;
COMPND 4 EC: 4.1.3.7

Comme il faut être feignant, j'aurais écrit

$ awk -v k="COMPND" '($1==k){print;}' 6CSC.pdb

ce qui donne le même résultat.

Pour continuer à jouer un peu avec -v, on peut aussi l'utiliser pour choisir des colonnes au moment de l'exécution. Pour cela, il suffit d'ajouter un "$" devant le nom de la variable :

$ k=1
$ awk -v var=$k -v var2=expr $k + 1 '{print $var,$var2;}' 6CSC.pdb | head -3
HEADER OXO-ACID-LYASE
TITLE CHICKEN
TITLE 2

Comme présenté dans la note de Leo_01, nous pourrions faire un grep pour extraire des lignes, mais ici l'avantage est de pouvoir en plus spécifier la colonne dans laquelle on cherche le mot.
Voila, c'est tout pour cette fois. Je pense que vous êtes prêt à passer à la pratique et à résoudre l'exercice en un tour de main. Au pire la solution se trouve plus bas (passer le curseur de la souris dessus pour la voir apparaitre).

[spoiler]

 $ for i in cut -d" " -f1 6CSC.pdb | sort | uniq -c | sort -k1,1n | tail -4 | awk '{print $2}'; do awk -v k=$i '($1==k){print;}' 6CSC.pdb > ${i}.txt; done

[/spoiler]



Pour continuer la lecture :


Commentaires

Une réponse à “Command line Tips : passage de variable dans awk”

  1. trés bon article pour debu­ter avec les clus­ter mer­ci !!!!!

Laisser un commentaire