sed: exclui todas as últimas X linhas de um arquivo, exceto as últimas X

sed: exclui todas as últimas X linhas de um arquivo, exceto as últimas X

Isso pode ser feito com outras ferramentas, mas estou interessado em saber como posso excluir todas as últimas X linhas do arquivo com a extensão sed.

Responder1

Basicamente você está emulando tail. X = 20 neste exemplo. O exemplo a seguir excluirá todas as últimas 20 linhas:

sed -i -e :a -e '$q;N;21,$D;ba' filename

Explicação:

  • O -e :a cria um rótulo chamado
  • O próximo -e:
    • $q - sai e imprime o espaço do padrão se for a última linha
    • N - próxima linha
    • 21,$D - executa o comando "D" se a linha# for >= 21 (21,$ = 21ª linha até $ que é o final do arquivo)
    • ba - ramifica para o rótulo 'a', que é o início do script.

Responder2

sedé bastante complexo quando se trata de tarefas como esta. tail, grepou awktornaria isso muito mais fácil e deveria ser usado. Dito isto, éépossível.

A seguinte solução é adaptada desed e pesquisa e substituição multilinha.

sed -ni '
    # if the first line copy the pattern to the hold buffer
    1h
    # if not the first line then append the pattern to the hold buffer
    1!H
    # if the last line then ...
    ${
            # copy from the hold to the pattern buffer
            g
            # delete current line if it is followed by at least X more lines
            # replace X-1 with the proper value
            s/.*\n\(\(.*\n\)\{X-1\}\)/\1/
            # print
            p
    }
' filename

Sem os comentários, é uma frase bacana. Se você quiser eliminar, por exemplo, tudo menos as últimas dez linhas, use isto:

sed -ni '1h;1!H;${;g;s/.*\n\(\(.*\n\)\{9\}\)/\1/;p;}' filename

Responder3

Baseado no roteiro emseção 4.13 do manual sedvocê poderia fazer algo assim:

n=10

(( n > 1 )) && script='1h; 2,'$n'{H;g;}; $q; 1,'$((n-1))'d; N; D'
(( n > 1 )) || script='$!d'

sed -i "$script" infile

Responder4

tac|sed|tac>&&(mv||cat>)

Ambos os trechos de comando a seguir excluirão efetivamente todos, exceto o própriodurar5linhasde ~/file1. Se você quiser manter odurar10linhas, você pode substituir: |sed '1,5!d;'por |sed '1,10!d;',e assim por diante, como achar melhor.

  1. tac ~/"file1" |sed '1,5!d;' |tac >"/tmp/file2" &&mv  "/tmp/file2"  ~/"file1"
  2. tac ~/"file1" |sed '1,5!d;' |tac >"/tmp/file2" &&cat "/tmp/file2" >~/"file1"

informação relacionada