Como apagar cada segunda linha de um arquivo?

22

Arquivo:

Data inserted into table. Total count 13
No error occurred
Data inserted into table. Total count 45
No error occurred
Data inserted into table. Total count 14
No error occurred
Data inserted into table. Total count 90
No error occurred

Arquivo de saída esperado:

Data inserted into table. Total count 13
Data inserted into table. Total count 45
Data inserted into table. Total count 14
Data inserted into table. Total count 90

Eu quero que a saída seja assim: cada segunda linha será excluída, mas não haverá espaço entre as linhas.

    
por pmaipmui 03.08.2015 / 11:44

9 respostas

34

com sed :

sed -e n\;d <file

Com POSIX awk :

awk 'FNR%2' <file

Se você tem mais awk (como oawk ), precisa:

oawk 'NR%2 == 1' <file

com ex :

$ ex file <<\EX
:g/$/+d
:wq!
EX

edita o arquivo no local.

  • g marca um comando global
  • /$/ corresponde a todas as linhas
  • +d elimina a linha seguinte
  • wq! salva todas as alterações

Essa abordagem compartilha o mesmo ideal com a abordagem sed , exclua todas as próximas linhas do início da linha atual da linha 1.

com perl :

perl -ne 'print if $. % 2' <file

e perl6 :

perl6 -ne '.say if $*IN.ins % 2' <file
perl6 -ne '.say if ++$ % 2' <file
    
por 03.08.2015 / 11:58
62

Resolver isso excluindo cada segunda linha pode ser propenso a erros (por exemplo, quando o processo às vezes gera duas linhas significativas, em vez de uma). Pode ser melhor filtrar o lixo:

grep -v "No error occurred" file

Ele pode ser executado como filtro, você pode adicionar mais padrões de lixo aqui e melhorar o resultado.

    
por 03.08.2015 / 14:27
11

Pegando a pergunta, com GNU sed :

sed '0~2d' file

excluirá todas as segundas linhas, mas eu gostaria de oferecer linhas de filtro pelo conteúdo:

sed '/Data/! d' file

ou com o mesmo resultado

sed '/No error/d' file
    
por 03.08.2015 / 12:02
5

Aqui está uma maneira de usar o sed :

sed -n 'p;n' filename

Outra maneira com o GNU sed :

sed -n '1~2p' filename

Saída dos comandos acima:

Data inserted into table. Total count 13
Data inserted into table. Total count 45
Data inserted into table. Total count 14
Data inserted into table. Total count 90
    
por 03.08.2015 / 13:28
4

Você pode tentar com awk :

awk 'NR % 2 != 0' file

ou você pode imprimir apenas linhas contendo Data inserted :

awk '$0 ~ /Data inserted/' file
    
por 03.08.2015 / 11:51
3

Outra resposta, você poderia usar o vi / vim!

qdjddq

E se o seu arquivo tiver 500 linhas (por exemplo), digite

250@d

E depois, para escrever e sair do tipo

:x

Ou se algo der errado e você não quiser salvar:

:q!

Explicação:

q      #Start Recording
 d     #Put the recording into register 'd'
  j    #Move the cursor down
   dd  #Delete the line
     q #Stop recording


250    #Number of repeats
   @d  #Playback the recording in register 'd'.
    
por 03.08.2015 / 17:31
2

Aqui está uma maneira bem diferente de fazer isso:

< file paste - - | cut -f1

Isso pressupõe que as linhas ímpares não contenham guias. Em caso afirmativo, você precisará escolher outro caractere separador, por exemplo : aqui:

< file paste -d: - - | cut -d: -f1
    
por 06.08.2015 / 04:38
1

Outra opção (mais curta)

sed 'n; d' file
    
por 03.08.2015 / 14:39
0

Também resolve o problema, embora seja um pouco mais lento:

vim -c "%normal jdd" -c "wq" file
    
por 07.08.2015 / 09:12