Astuce shell : afficher certaines lignes d'un résultat

Mise à jour 28/09/2009 : refonte et enrichissement de l'article suite aux commentaires reçus, merci à tous !

Dans les scripts shell, j'ai parfois besoin d'afficher certaines lignes d'un résultat comprenant un nombre de lignes variable.

$ cat liste.txt
**Ligne d'en-tête**
toto
tata
...
titi
tutu
$

Nous allons étudier 2 solutions possibles :

  • solution basique avec head et tail
  • solution avancée avec sed

 

Solution basique : head et tail

Avec les commandes head et tail, on peut n'afficher que les n premières ou dernières lignes d'un résultat.

$ head -n 1 liste.txt #affiche la première ligne
**Ligne d'en-tête**
$ tail -n 2 liste.txt #affiche les 2 dernières lignes
titi
tutu
$

On peut également utiliser head et tail pour afficher toutes les lignes sauf les n premières ou dernières.

$ head -n -1 liste.txt #tout sauf la ligne 1
toto
tata
...
titi
tutu
$ tail -n +3 liste.txt #tout à partir de la ligne 3
tata
...
titi
tutu

 

Solution avancée : sed

Alternativement on peut utiliser sed, plus complexe mais bien plus puissant. Nous allons nous intéresser aux commandes d (pour delete) et p (pour print) ainsi qu'à l'option -n (sed affiche chaque ligne par défaut, -n inverse ce comportement et sed n'affichera plus les lignes par défaut). Notons également le caractère $, qui désigne la dernière ligne dans les commandes d et p de sed.

$ sed -n '2p' liste.txt #affiche la ligne 2 
tata
$ sed -n '$p' liste.txt #affiche la dernière ligne
tutu
$ sed '3d' liste.txt #supprime la ligne 3
**Ligne d'en-tête**
toto
...
titi
tutu

Sed permet également de sélectionner des plages de lignes. La syntaxe la plus simple est la suivante :

$ sed '2,3d' liste.txt #supprime les lignes 2 à 3
**Ligne d'en-tête**
...
titi
tutu
$ sed -n '3,$p' liste.txt #affiche de la ligne 3 à la fin
tata
...
titi
tutu

Mais sed permet des comportements plus complexes en sélectionnant les lignes non pas avec des numéros mais avec des expressions régulières. Très utile pour créer un petit système de templates par exemple.

Les expressions régulières sont encadrées par des barres obliques ("/").

$ sed -n '1,/titi/p' liste.txt #affiche les lignes entre 1 et /titi/
**Ligne d'en-tête**
toto
tata
...
titi
$ sed -n '/toto/,/titi/p' liste.txt #affiche les lignes entre /toto/ et /titi/
toto
tata
...
titi

Note : sed sélectionne toujours la première ligne correspondant à l'expression régulière en cas de résultat multiple. Dans l'exemple ci-dessous, la première ligne correspondante est "foobaz" :

$ cat test.txt
foo
foobar
foobaz
baz
bar
$ sed '/foo/,/baz/d' #supprime les lignes entre /foo/ et /baz/
baz
bar

Cela fonctionne aussi pour les expressions plus complexes, par exemple :

$ sed '/f[o]\\{2\\}/,/^b[:alpha:]\\?[rz]/d'
bar

 

Conclusion

Avec ces quelques commandes, il devient possible de filtrer finement les lignes d'un résultat que l'on souhaite récupérer.

Vus : 1251
Publié par Linalis : 17