Esta tarefa é mais facilmente realizada processando as linhas do arquivo na ordem oposta.
tac infile | awk 'flag {print} {if(NF) flag=1}' | tac | sponge infile
Como apontado nos comentários de Malte Skoruppa e zwets, o Ubuntu não vem com o pacote moreutils pré-instalado, que contém sponge ; uma solução alternativa é usar uma substituição de comando dentro de um travessão para ler o arquivo de entrada, para que, sendo a substituição do comando processada primeiro, o arquivo seja seguro para ser truncado pelo segundo comando tac :
<<<"$(< infile)" tac | awk 'flag {print} {if(NF) flag=1}' | tac > infile
-
tac infile: ... faz o oposto decat infile(!): imprime o arquivo emstdoutinvertendo a ordem da linha; -
awk [...]: processa o arquivo; -
tac: ... faz o oposto decat(!): imprime o arquivo emstdoutinvertendo a ordem da linha; -
sponge infile: envia parainfileapenas quando o lado esquerdo do canal terminou sua execução, para evitar truncarinfileantes de ser lido pelo primeiro comandotac;
% de colapso do comandoawk:
-
flag {print}: seflagestiver definido, a linha será impressa;flagnão será definido até que um registro cujoNFcorresponda a um número maior que0seja processado, portanto, até que um registro cujo valorNFcorresponda a um número maior que0não encontrado, a% O comandoprintserá ignorado; -
{if(NF) flag=1}: se enquantoflagainda não foi definido um registro cujoNFcorresponde a um número maior que0é processado, ele não será impresso eflagserá definido como1, então o primeiro registro cujo valorNFcorresponde a um número maior que0não será impresso;
Teste em um arquivo de teste (lembre-se de que a linha 4 e a linha 7 contêm 5 espaços, enquanto a linha 5 e a linha 8 estão vazias):
user@debian ~ % cat infile
line1
line2
line3
line6
user@debian ~ % tac infile | awk 'flag {print} {if(NF) flag=1}' | tac
line1
line2
line3
user@debian ~ %
A linha 7 e a linha 8 foram removidas porque estavam ambas no final do arquivo, contendo apenas espaços (linha 7) ou contendo nada (linha 8); a linha 6 foi excluída porque foi a primeira, lendo as linhas do arquivo na ordem oposta, para ter pelo menos um campo (portanto, não estando vazio ou contendo apenas espaços)