Como pop (ler e remover) uma linha de um arquivo?

6

Estou tentando obter a última linha de um arquivo e excluí-lo:

Leia a linha:

sed -n '$p' file
# or
tail -n 1 file

Remova a linha:

sed -i '$d' file

Isso funciona, mas existe uma maneira de fazer isso com apenas um único comando ?

    
por RoVo 11.10.2018 / 15:45

2 respostas

10
Seja qual for a sabedoria predominante, ter que ler um arquivo inteiro a cada vez para cortar sua última linha é mudo , não importa se é feito em um único processo / comando ou dois ou três .

Ao contrário de sed -i , tail é inteligente o suficiente para não ler um arquivo desde o início para determinar qual é sua última linha; também, o linux tem um utilitário truncate(1) , que combinado com tail permite que você "insira" a (s) última (s) linha (s) de um arquivo grande no tempo O (1):

# usage popline file [line_count, 1 by default]
popline(){ LC_CTYPE=C l='tail -"${2:-1}" "$1"; echo t'; l=${l%t}; truncate -s "-${#l}" "$1"; printf %s "$l"; }

$ wc -l /tmp/foo
687800 /tmp/foo
$ cp /tmp/foo /tmp/foo1 && time sed -i '$d' /tmp/foo1

real    0m1.185s
user    0m0.196s
sys     0m0.984s
$ cp /tmp/foo /tmp/foo1 && time popline /tmp/foo1
 */

real    0m0.082s
user    0m0.000s
sys     0m0.000s
    
por 11.10.2018 / 17:54
7

O objetivo é ter um único comando que produza a última linha de um arquivo e, ao mesmo tempo, exclua essa linha do arquivo original.

sed -i -e '${w /dev/stdout' -e 'd;}' file

Isso executaria o seguinte script sed :

${
    w /dev/stdout
    d
}

Isso grava a última linha em /dev/stdout e depois a exclui. Todas as outras linhas são gravadas no arquivo original por meio da opção -i .

O script na linha de comando deve ser dividido em dois, pois não há como, de outra forma, delimitar o nome do arquivo de saída do comando w (além de inserir uma nova linha literal).

com ed :

ed -s file <<END_ED
p
d
w
END_ED

ed abre o arquivo file e coloca o cursor na última linha do arquivo. O primeiro comando imprime essa linha na saída padrão, a segunda a exclui e o último comando grava o buffer de volta no arquivo. Usar ed desta maneira pode não ser aconselhável em arquivos grandes.

    
por 11.10.2018 / 15:53