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

5

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

    
por Felipe Alvarez 07.09.2012 / 04:10

4 respostas

9

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

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

Explicação:

  • O -e: a cria um rótulo chamado
  • O próximo -e:
    • $ q - fecha e imprime o espaço de 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 para $, que é o final do arquivo)
    • ba - ramificações para rotular 'a', que é o começo do script.
por 07.09.2012 / 07:13
6

sed é bastante complexo quando se trata de tarefas como essa. tail , grep ou awk facilitaria muito isso e deveria ser usado em seu lugar. Dito isto, é possível .

A seguinte solução é adaptada de sed e Multi-Line Search and Replace .

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\}\)//
            # print
            p
    }
' filename

Sem os comentários, ele faz uma bela linha de uma linha. Se você quiser eliminar, por exemplo, tudo menos as últimas dez linhas, use:

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

Baseado no script da seção 4.13 do manual do sed , você pode 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
    
por 07.09.2012 / 10:16
0

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

Ambos os snippets de comando a seguir excluem efetivamente todas as últimas 5 linhas de ~/file1 . Se você quiser manter as últimas 10 linhas , poderá substituir: |sed '1,5!d;' por |sed '1,10!d;' , e assim por diante , como você vê em forma.

  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"
por 05.06.2016 / 22:45

Tags