Obtenha o último conjunto de linhas não vazias

2

Estou executando uma tarefa do cron que deve receber apenas o último resultado de iostat -d 1 2 . Isso requer alguma análise: Qual é a maneira mais simples de obter o último conjunto de linhas não vazias da entrada padrão para a saída padrão se o tamanho de cada conjunto for desconhecido?

Soluções ruins / não funcionais:

  • tail , pois ainda precisaria contar o número de linhas no último conjunto. iostat -d 1 2 | tail -$(echo "$(iostat -d 1 2 | wc -l) / 2" | bc) depende dos tamanhos de conjuntos iguais.
  • split / csplit , pois eles enviam para o arquivo e mantêm a parte inútil dos dados.
  • iostat -d 1 2 | sed '1,/^$/d' | sed '1,/^$/d' funciona apenas neste caso especial, pois obtém o terceiro conjunto de linhas não vazias, mas também inclui quaisquer novas linhas finais.
  • iostat -d 1 2 | tac | sed '1,/^$/d' | sed '/^$/q' é um hack ligeiramente melhor: Inverta e imprima o primeiro conjunto. No entanto, como iostat produz uma linha vazia no final, primeiro removemos essa linha e depois imprimimos até a próxima linha vazia na saída invertida. Outros comandos podem gerar qualquer número de novas linhas no final, portanto, não é uma solução geral. Inverta novamente se quiser manter a sequência original.
  • grep -P com \Z parece detectar apenas EOL, não EOF.
por l0b0 17.03.2011 / 10:40

3 respostas

6

Você pode usar o modo de parágrafo de awk (quando RS é a string vazia). Dessa forma, cada "set" é um registro e você pode imprimir facilmente o último.

iostat -d 1 2 | awk -vRS= 'END{print}'
    
por 17.03.2011 / 11:49
4

perl -00 é uma boa maneira de ler um parágrafo de cada vez, então o último parágrafo é:

perl -00 -ne '$para = $_; END {print $para}'
    
por 17.03.2011 / 11:55
2

com sed :

sed '/^$/{$!{N;/\n$/D;s/.//;$!h;$p;d};};//!{H;1h;$!d};$x' infile

isso deve imprimir o último conjunto de linhas não vazias sem nenhuma linha vazia inicial / final.
por exemplo,

iostat -d 1 2 | sed '/^$/{       # if the line is empty
$!{                              # and if it's not the last line
N                                # then pull in the next line
/\n$/D                           # if also empty, delete up to \n, restart cycle
s/.//                            # otherwise delete leading \newline 
$!h                              # copy over hold space if not last line
$p                               # or print pattern space if last line
d                                # then delete pattern space
}
}
//!{                             # if the line isn't empty
H                                # append it to hold space
1h                               # if it's the first line, overwrite hold space
$!d                              # if it's not the last line, delete it
}
$x                               # on the last line, exchange buffers
'
    
por 01.08.2015 / 21:03