Eu tenho essa saída.
[root@linux ~]# cat /tmp/file.txt
virt-top time 11:25:14 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.0 0.0 96:02:53 instance-0000036f
2 R 0 0 0 0 0.0 0.0 95:44:07 instance-00000372
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
Você pode ver que ele tem dois blocos e eu quero extrair o último bloco (se você vir o primeiro bloco, ele tem toda a CPU zero, o que eu não me importo) resumindo, quero extrair seguindo as últimas linhas (Observações: às vezes eu tenho mais de duas instâncias -*) caso contrário eu poderia usar "tail -n 2"
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
Eu tentei sed/awk/grep e todas as formas possíveis, mas não cheguei perto do resultado desejado.
Isso parece um pouco bobo, mas:
O GNU
tac
reverte o arquivo (muitos sistemas não-GNU têmtail -r
), assed
linhas escolhem até a primeira que começa comvirt-top
. Você pode adicionarsed 1,2d
outail -n +3
remover os cabeçalhos.Ou em awk:
Ele apenas coleta todas as linhas de uma variável e limpa essa variável em uma linha que começa com
virt-top
.Se o arquivo for muito grande, a solução
tac
+sed
provavelmente será mais rápida, pois ela só precisa ler o final do arquivo enquanto aawk
solução lê o arquivo completo a partir do topo.Com
ed
você pode buscar regex para cima usando?pattern?
no lugar do usual/pattern/
(que busca acima da posição atual). Assim, por exemplo:Se sua entrada tiver um número fixo de blocos, você também poderá fazer algo como:
Para produzir as linhas da 2ª ocorrência de
virt-top
até o final do arquivo (0 significa false , significa que o final desse primeiro e último intervalo nunca é encontrado).Obtendo o último registro da linha que começa com a string
virt-top
até o final usandoed
(adequado para lidar com arquivos de tamanho comparável ao que você mostra, não vários megabytes grandes):Ou, apenas as linhas após a última
virt-top
linha que contém a substringinstance
:Esse último
ed
comando,?^virt-top?,$g/instance/p
, primeiro designa um intervalo de linhas da última linha que começa comvirt-top
(último, porqueed
você começa na última linha do buffer e?re?
pesquisa para trás) até o final do buffer ($
) e aplica o comandog/instance/p
a esses linhas. Og/re/p
comando imprime todas as linhas dentro do intervalo que corresponde à expressão regular fornecida (grep
a propósito, foi daí que veio o nome).Usando
awk
:Isso salva linhas de entrada
lines
sempre que houver uma linha que contenha a substringinstance
. Estas linhas são impressas no final. Sempre que uma linha que começa comvirt-top
é encontrada, as linhas salvas são descartadas.Praticamente a mesma coisa com
sed
, usando o espaço de espera para servir como o equivalente dalines
variável noawk
código:Aqui está mais um método para lidar com isso:
Resultados