Получение последней записи из строки, начинающейся со строки virt-top
, в конец с помощью ed
(, подходящей для работы с файлами размером, сравнимым с тем, что вы показываете, а не размером в несколько мегабайт):
$ printf '%s\n' '?^virt-top?,$p' | ed -s file
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
Или только строки после последней virt-top
строки, содержащие подстрокуinstance
:
$ printf '%s\n' '?^virt-top?,$g/instance/p' | ed -s file
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
Эта последняя команда ed
, ?^virt-top?,$g/instance/p
, сначала назначает диапазон строк от последней строки, которая начинается сvirt-top
(последней, потому что ed
запускает вас с последней строки буфера, а ?re?
выполняет поиск назад )до конца буфера($
)и применяет к этим строкам команду g/instance/p
. Команда g/re/p
выводит все строки в диапазоне, который соответствует заданному регулярному выражению (, откуда grep
и получил свое название, кстати ).
Использованиеawk
:
$ awk '/^virt-top/ { lines = "" } /instance/ { lines = (lines == "" ? $0 : lines ORS $0) } END { print lines }' file
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
Это сохраняет строки ввода в lines
всякий раз, когда есть строка, содержащая подстроку instance
. Эти строки печатаются в конце. Всякий раз, когда обнаруживается строка, начинающаяся с virt-top
, сохраненные строки отбрасываются.
Практически то же самое с sed
, с использованием пробела хранения в качестве эквивалента переменной lines
в коде awk
:
$ sed -n '/^virt-top.*/{ s///; x; d; }; /instance/H; ${ x; s/\n//; p; }' file
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