Accessibility Tools

- Le blog participatif de bioinformatique francophone depuis 2012 -

Analyse de fichiers dans le bon vieux temps ! | Creative Commons 2.0, wikimedia
Analyse de fichiers dans le bon vieux temps ! | Creative Commons 2.0, wikimedia

Langage : shell, sous GNU/​Linux

Commandes présentées :wc, awk, sed, tr, head, nl, cut

Niveau : débutant

Dans le cadre de notre travail, nous sommes souvent amenés à manipuler de nombreux fichiers contenant des milliers de lignes et des dizaines de champs. Dans ces cas-​là, nous avons souvent tendance à virer à la paranoïa et à vouloir nous assurer que nos fichiers sont bien formatés et contiennent bien le nombre de lignes, champs ou éléments attendus.

Dans ce billet, je vous propose de découvrir ou redécouvrir quelques commandes simples pour analyser rapidement des fichiers.

Pour les différents exemples montrés, je vous ai préparé de petits fichiers que vous pouvez récupérer pour tester les exemples. Vous pouvez les récupérer en cliquant sur les liens suivants :

Afficher le nombre de lignes

wc -l exemple_wc.txt

Un grand classique mais c'est le meilleur moyen de s'assurer que l'on a bien le bon nombre de lignes attendu. C'est également un bon moyen de vérifier que vous n'avez pas un fichier contenant des retours à la ligne de Windows, les fameux ^M ou CRLF.
Si vous avez de tels sauts de lignes, la commande vous affichera 0 lignes, et la commande dos2unix peut vous être utile.
Résultat attendu :

5 exemple_wc.txt

Retirer la première ligne d'un fichier

sed '1d' exemple_sed.txt

Renverra sur la sortie standard le contenu du fichier exemple_sed.txt sans la première ligne.
Résultat attendu :

Si cette ligne est la première, c'est que vous avez bien supprimé la première ligne.
La troisième ligne.
La quatrième ligne.
La cinquième ligne.
Et toutes les autres lignes que vous voulez.

Ligne non affichée :

Ceci est la première ligne.

Attention, sed ne supprimera pas la première ligne dans le fichier, la commande se contentera de ne pas l'afficher. Il faudra ajouter l'option -i (mode insertion) pour la supprimer directement dans le fichier.
Exemple :

nolwenn@bioinfo-fr$ cp exemple_sed.txt exemple_sed_insert.txt
nolwenn@bioinfo-fr$ wc -l exemple_sed_insert.txt
6 exemple_sed_insert.txt
nolwenn@bioinfo-fr$ sed -i '1d' exemple_sed_insert.txt
nolwenn@bioinfo-fr$ wc -l exemple_sed_insert.txt
5 exemple_sed_insert.txt
nolwenn@bioinfo-fr$ cat exemple_sed_insert.txt
Si cette ligne est la première, c'est que vous avez bien supprimé la première ligne.
La troisième ligne.
La quatrième ligne.
La cinquième ligne.
Et toutes les autres lignes que vous voulez.

Afficher les numéros de colonnes d'un fichier

head -n 1 exemple_numcol.tsv | tr "\t" "\n" | nl

head -n 1 affiche la première ligne.
tr permet de "traduire" la tabulation par un retour à la ligne.
nl permet d'afficher le numéro de la ligne lue.

Si vous ne connaissez pas le symbole pipe "|", je vous recommanderai de lire l'article sur les pipelines rédigé par Akira.

Remplacer \t par le séparateur de colonnes de votre choix.
Merci à S. Letort pour cette astuce à mon arrivée dans l'unité.
Résultat attendu :

1  rs
2  pos
3  chrom

Afficher le nombre de lignes par nombre de champs

awk '{print NF}' exemple_awk.tsv | sort | uniq -c

print NF affiche le nombre de champs pour chaque ligne lue dans le fichier exemple_awk.tsv par awk.
sort tri le flux de sortie de awk.
uniq -c compte le nombre de lignes identiques
Résultat attendu :

2 3
1 5
1 9

Dans cet exemple, nous avons donc 2 lignes contenant 3 champs, 1 ligne contenant 5 champs et 1 ligne faisant 9 champs.

Merci à A. Vaysse pour cette astuce (et pour m'avoir appris le awk).
Très utile pour vérifier qu'un fichier à bien le bon nombre de champs pour chaque ligne.

Récupérer les champs d'intérêt d'un fichier

La commande cut permet de découper un fichier champ par champ, ou colonne par colonne. Les champs sont considérés comme des index, un peu comme une liste en langage Python ou Perl. L'index de cut commence par 1, en Python et en Perl les index commencent par 0.

cut -f 3 exemple_cut.tsv

Affiche le champs 3.
Résultat attendu :

3
c
m
w
cut -f 1,4 exemple_cut.tsv

Affiche les champs 1 et 4.
Résultat attendu :

1   4
a   d
k   n
u   x
cut -f 3-7 exemple_cut.tsv

Affiche les champs 3 à 7.
Résultat attendu :

3   4   5   6   7
c   d   e   f   g
m   n   o   p   q
w   x   y   z   aa
cut --complement -f 1-3 exemple_cut.tsv

Affiche tous les champs à l'exception des champs 1 à 3.
Résultat attendu :

4   5   6   7   8   9   10
d   e   f   g   h   i   j
n   o   p   q   r   s   t
x   y   z   aa  bb  cc  dd

Conclusion

En conclusion, je vous avouerai que j'utilise assez fréquemment ces lignes de commandes. En fonction de la complexité des données contenues je jongle entre ces différentes commandes tout en utilisant les pipelines.

Il existe sûrement d'autres astuces que j'ai oublié ou que je ne connais pas, aussi si vous en connaissez je vous invite à les partager entre nous dans les commentaires de ce billet !

Merci à Yoann M. et Mica pour vos relectures et vos commentaires.



Pour continuer la lecture :


Commentaires

9 réponses à “Analyses rapides de fichiers”

  1. Avatar de Cédric

    Merci pour cet article. Pour la vérification de fichiers et bien au delà, voici deux mines de one-​line en sed et en awk dans lesquelles je vais souvent fouiller.

  2. D'une manière générale en bioinfo, il est utile d'exporter la variable d'environement

    LC_ALL=C
    
    les comparaisons se font au niveau des bytes, en ignorant les "Locale" = plus rapide. Par exemple:
    
    LC_ALL=C sort -k1,1 -k2,2 file.bed
    
    cf. http://www.biostars.org/p/45456/
    1. typo

      LC_ALL=C sort -k1,1 -k2,2n file.bed
      
      1. Merci pour l'astuce, ça va être utile je pense 😉

    2. Merci pour votre commentaire.
      Il est intéressant de constater les différences en terme de performance avec juste ce changement de variable d'environnement.
      Savez-​vous à quoi cela est-​il dû ?

  3. Avatar de Nicolas Belouin
    Nicolas Belouin

    Si j'ai bien compris la chose. Cela est dû au fait que, par défaut, l'environnement utilise l'encodage UTF-​8 qui peut remplir jusqu'à 4 octets et nécessite l'ouverture de plusieurs fichiers. En passant la commande LC_ALL=C, on définit un jeu de caractère ASCII encodé sur un seul octet nécessitant moins d'ouvertures. Je suppose que les chaînes de caractères en sont traités plus rapidement et les accès disque moins nombreux.
    Par contre il faut faire attention, LC_ALL=C modifie le comportement de la commande sort :
    par défaut :
    a
    A
    b
    B

    avec LC_ALL=C
    A
    B
    C
    a
    b
    c

    En espérant ne pas dire trop de bêtises, et merci pour les petites astuces 😉

  4. Avatar de Alexis MICHON
    Alexis MICHON

    Très bon job de résumer des commandes utiles.

  5. Avatar de Amandine

    Merci pour ces astuces !

  6. Avatar de Aymeric Inpong
    Aymeric Inpong

    "Bel article d'apprentissage ! Aymeric Inpong"

Laisser un commentaire

Pour insérer du code dans vos commentaires, utilisez les balises <code> et <\code>.