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

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

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.


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

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


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

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

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


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

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'


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

-2

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

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


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.