C'est un peu idiot, mais :
$ tac file.txt |sed -e '/^virt-top/q' |tac
virt-top time 11:25:17 Host foo.example.com x86_64 32/32CPU 1200MHz 65501MB
ID S RDRQ WRRQ RXBY TXBY %CPU %MEM TIME NAME
1 R 0 0 0 0 0.6 12.0 96:02:53 instance-0000036f
2 R 0 0 0 0 0.2 12.0 95:44:08 instance-00000372
GNU tac
inverse le fichier (de nombreux systèmes non-GNU ont tail -r
à la place), le sed
sélectionne les lignes jusqu'à la première qui commence par virt-top
. Vous pouvez ajouter sed 1,2d
ou tail -n +3
pour supprimer les en-têtes.
Ou en awk :
$ awk '/^virt-top/ { a = "" } { a = a $0 ORS } END {printf "%s", a}' file.txt
virt-top time 11:25:17 Host foo.example.com x86_64 32/32CPU 1200MHz 65501MB
ID S RDRQ WRRQ RXBY TXBY %CPU %MEM TIME NAME
1 R 0 0 0 0 0.6 12.0 96:02:53 instance-0000036f
2 R 0 0 0 0 0.2 12.0 95:44:08 instance-00000372
Il collecte simplement toutes les lignes d'une variable et efface cette variable sur une ligne commençant par virt-top
.
Si le fichier est très volumineux, le tac
+sed
solution est forcément plus rapide puisqu'elle n'a besoin que de lire la fin du fichier tandis que le awk
la solution lit le fichier complet à partir du haut.
Avec ed
vous pouvez effectuer une recherche régulière vers le haut en utilisant ?pattern?
à la place de l'habituel /pattern/
(qui recherche par dessus la position actuelle). Ainsi, par exemple :
$ printf '%s\n' '?ID?+1,$p' q | ed -s file.txt
1 R 0 0 0 0 0.6 12.0 96:02:53 instance-0000036f
2 R 0 0 0 0 0.2 12.0 95:44:08 instance-00000372
Si votre entrée a un nombre fixe de blocs, vous pouvez également faire quelque chose comme :
awk '/^virt-top/ && ++n == 2, 0' <your-file
Pour sortir les lignes de la 2 occurrence de virt-top
à la fin du fichier (0 signifiant faux , signifie la fin de ce premier ,dernier la plage n'est jamais trouvée).