Excluir primeira linha de um arquivo

110

Como posso excluir a primeira linha de um arquivo e manter as alterações?

Eu tentei isso, mas apaga todo o conteúdo do arquivo.

$sed 1d file.txt > file.txt
kickass13
fonte

Respostas:

81

O motivo file.txt está vazio após esse comando é a ordem na qual o shell faz as coisas. A primeira coisa que acontece com essa linha é o redirecionamento. O arquivo "file.txt" é aberto e truncado para 0 bytes. Depois disso, o comando sed é executado, mas no momento o arquivo já está vazio.

Existem algumas opções, a maioria envolve a gravação em um arquivo temporário.

sed '1d' file.txt > tmpfile; mv tmpfile file.txt # POSIX
sed -i '1d' file.txt # GNU sed only, creates a temporary file

perl -ip -e '$_ = undef if $. == 1' file.txt # also creates a temporary file
jordanm
fonte
2
Com o BSD sed, você pode usar sed -i .bak '1d' file.txt.
1
existe uma maneira que não inclua o arquivo temporário? De qualquer forma, isso fará o truque. Muito obrigado!
kickass13
@ kickass13 possivelmente usando um editor de texto como ed.
Jordanm #
6
O edcomando seria: printf "%s\n" 1d w q | ed file.txt(I heart ed)
glenn jackman
1
@jonayreyes-exec sed -i '1d' {} \;
jordanm
141

Uma opção alternativa muito leve é ​​apenas para 'arrastar' tudo, exceto a primeira linha (essa pode ser uma maneira fácil de remover os cabeçalhos de arquivos em geral):

# -n +2 : start at line 2 of the file.
tail -n +2 file.txt > file.stdout

Seguindo @Evan Teitelman, você pode:

tail -n +2 file.txt | sponge file.txt

Para evitar um arquivo temporário. Outra opção pode ser:

echo "$(tail -n +2 file.txt)" > file.txt

E assim por diante. Testando o último:

[user@work ~]$ cat file.txt
line 1
line 2
line 3
line 4
line 5

[user@work ~]$ echo "$(tail -n +2 file.txt)" > file.txt
[user@work ~]$ cat file.txt
line 2
line 3
line 4
line 5
[user@work ~]$ 

Opa, perdemos uma nova linha (de acordo com o comentário @ 1_CR abaixo), tente:

printf "%s\n\n" "$(tail -n +2 file.txt)" > file.txt

[user@work ~]$ cat file.txt
line 1
line 2
line 3
line 4
line 5

[user@work ~]$ printf '%s\n\n' "$(tail -n +2 file.txt)" > file.txt
[user@work ~]$ cat file.txt
line 2
line 3
line 4
line 5  

[user@work ~]$ 

Voltando ao sed, tente:

printf '%s\n\n' "$(sed '1d' file.txt)" > file.txt

ou talvez

echo -e "$(sed '1d' file.txt)\n" > file.txt

Para evitar efeitos colaterais.

AsymLabs
fonte
Eu apenas tentei no meu sistema Fedora e a saída está acima. Você está correto - obrigado por apontar isso.
AsymLabs
O tailtruque funcionou para mim (levou menos de 3 segundos em um arquivo de 130mb). Obrigado!
Elo80ka
echo "$(tail -n +2 file.txt)" > file.txté a resposta perfeita.
Alex Raj Kaliamoorthy
Obrigado! echo "$ (tail -n +2 file.txt)"> file.txt funciona para mim como um encanto!
Arsenii
16

Também dê uma olhada spongea partir moreutils. spongeabsorve os dados da entrada padrão até o final da gravação da entrada padrão fechar antes de gravar em um arquivo. É usado assim:

sed '1d' file.txt | sponge file.txt

fonte
14

Este tópico é de interesse, então testei o benchmark de três maneiras:

  1. sed '1d' d.txt > tmp.txt
  2. tail -n +2 d.txt > tmp.txt
  3. sed -i '1d' d.txt

Observe que o destino d.txté um arquivo de 5,4 GB

Obtenha o resultado:


run 1 : sed '1d' d.txt > r1.txt
14s
run 2 : tail -n +2 d.txt > r2.txt
20s
run 3 : sed -i '1d' d.txt
88s

Conclusão: Parece abaixo a maneira mais rápida:

sed '1d' file.txt > tmpfile; mv tmpfile file.txt

waue0920
fonte
Seu sed '1d' d.txtmétodo não incluiu (ou pelo que parece, lendo seus testes) o mvcomando. Nos meus testes no FreeBSD com um arquivo de 20 MB, sed -ifoi o mais rápido.
Sopalajo de Arrierez
9

expode ser usado para edição in-loco verdadeira que não envolve um arquivo temporário

ex -c ':1d' -c ':wq' file.txt
iruvar
fonte
2
ex usa um arquivo temporário. strace -e open ex -c ':1d' -c ':wq' foo. ex trunca o arquivo original com o arquivo temporário, onde a opção -i do GNU sed sobrescreve o original com o arquivo temporário. Não tenho certeza de como funciona o sed do BSD.
llua
@llua, você está certo. Notei isso também, mas mais tarde
iruvar
3

A maneira mais curta e simples de excluir a primeira linha de um arquivo usando sedé:

$ sed -i -n -e '2,$p' file.txt
starfry
fonte
3

Você pode usar o Vim no modo Ex:

ex -s -c '1d|x' file.txt
  1. 1 encontre a primeira linha

  2. d excluir

  3. x salvar e fechar

Steven Penny
fonte
0

Este comando removerá 1 linha e salvará como "file.txt".

sed '1d' file.txt  > /tmp/file.txt && mv /tmp/file.txt file.txt || rm -f /tmp/file.txt
Ritesh Singh
fonte
0

Para excluir uma linha praticiler no arquivo

  1. Excluir primeira linha

Arquivo Sed '1d'

  1. Excluir primeira e terceira linha

Arquivo '1d3d' sed

Excluir caractere em linha

1 Excluir as duas primeiras cartas em lin

Arquivo Sed 's /^..//'

2 Exclua as últimas duas linhas de chrectercin

Arquivo Sed / .. £ // '

3 Excluir linha em branco

Arquivo Sed '/ ^ £ / d'

Vivek parikh
fonte
4
Os britânicos retomaram as colônias? A última vez que olhei, £$.
G-Man
£ indicado doller sign ..
Vivek parikh 22/10/2015
0

Pode usar o vim para fazer isso:

vim -u NONE +'1d' +wq! /tmp/test.txt
Hongbo Liu
fonte
-2

arquivo de gato01 | sed -e '1,3d'

// mostra o conteúdo no arquivo01, mas remove a primeira e a terceira linha

user215264
fonte
2
o comando sed você dá irá remover as linhas 1, 2 e 3.
Icarus
1
Isso exclui mais do que é solicitado e não "mantém as alterações"
Jeff Schaller