Eliminar primera línea de un archivo

110

¿Cómo puedo eliminar la primera línea de un archivo y guardar los cambios?

Intenté esto pero borra todo el contenido del archivo.

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

Respuestas:

81

La razón por la que file.txt está vacío después de ese comando es el orden en que el shell hace las cosas. Lo primero que sucede con esa línea es la redirección. El archivo "file.txt" se abre y trunca a 0 bytes. Después de eso, se ejecuta el comando sed, pero en ese momento el archivo ya está vacío.

Hay algunas opciones, la mayoría implica escribir en un archivo temporal.

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
fuente
2
Con BSD sed, puede usar sed -i .bak '1d' file.txt.
1
¿Hay alguna manera que no incluya el archivo temporal? De todos modos, esto hará el truco. ¡Muchas gracias!
kickass13
@ kickass13 posiblemente usando un editor de texto como ed.
jordanm
66
El edcomando sería: printf "%s\n" 1d w q | ed file.txt(I heart ed)
glenn jackman
1
@jonayreyes-exec sed -i '1d' {} \;
jordanm
141

Una opción alternativa muy liviana es simplemente 'ajustar' todo menos la primera línea (esta puede ser una forma fácil de eliminar encabezados de archivos en general):

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

Siguiendo a @Evan Teitelman, puedes:

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

Para evitar un archivo temporal. Otra opción podría ser:

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

Etcétera. Prueba de la última:

[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 ~]$ 

Vaya, perdimos una nueva línea (según el comentario de @ 1_CR a continuación), intente en su lugar:

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 ~]$ 

Volviendo a sed, intente:

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

o quizás

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

Para evitar efectos secundarios.

AsymLabs
fuente
Lo acabo de probar en mi sistema Fedora y la salida está arriba. Estás en lo correcto, gracias por señalarlo.
AsymLabs
El tailtruco funcionó para mí (tardó menos de 3 segundos en un archivo de 130 MB). ¡Gracias!
elo80ka
echo "$(tail -n +2 file.txt)" > file.txtEs la respuesta perfecta.
Alex Raj Kaliamoorthy
¡Gracias! echo "$ (tail -n +2 file.txt)"> file.txt funciona para mí como un encanto!
Arsenii
16

También echa un vistazo a spongepartir moreutils. spongeabsorbe los datos de la entrada estándar hasta que el final de escritura de la entrada estándar se cierra antes de escribir en un archivo. Se usa así:

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

fuente
14

Este tema es de interés, por lo que pruebo el punto de referencia de 3 maneras:

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

Tenga en cuenta que el objetivo d.txtes un archivo de 5.4GB

Obtén el 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

Conclusión: a continuación parece ser la forma más rápida:

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

waue0920
fuente
Su sed '1d' d.txtmétodo no incluyó (o eso parece al leer sus pruebas) el mvcomando. En mis pruebas en FreeBSD con un archivo de 20 MB, sed -ifue el más rápido.
Sopalajo de Arrierez
9

exse puede usar para una verdadera edición in situ que no involucra un archivo temporal

ex -c ':1d' -c ':wq' file.txt
iruvar
fuente
2
ex usa un archivo temporal. strace -e open ex -c ':1d' -c ':wq' foo. ex trunca el archivo original con el archivo temporal, mientras que la opción -i de GNU sed sobrescribe el original con el archivo temporal. No estoy seguro de cómo funciona el sed de BSD.
llua
@llua, tienes razón. También me di cuenta de eso, pero más tarde
iruvar el
3

La forma más corta y sencilla de eliminar la primera línea de un archivo usando sedes:

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

Puede usar Vim en modo Ex:

ex -s -c '1d|x' file.txt
  1. 1 encontrar la primera línea

  2. d Eliminar

  3. x guardar y cerrar

Steven Penny
fuente
0

Este comando eliminará 1 línea y guardará como "file.txt".

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

Para eliminar una línea de praticiler en el archivo

  1. Eliminar primera línea

Archivo Sed '1d'

  1. Eliminar primera y tercera línea

Archivo Sed '1d3d'

Eliminar personaje en línea

1 Eliminar los dos primeros charter en lin

Archivo de Sed /^..//

2 Eliminar las dos últimas líneas de chrectercina

Archivo de Sed / .. £ //

3 Eliminar línea en blanco

Archivo Sed '/ ^ £ / d'

Vivek parikh
fuente
44
¿Los británicos retomaron las colonias? La última vez que miré, £$.
G-Man
£ indicaba signo doller ..
Vivek parikh
0

Podría usar vim para hacer esto:

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

cat file01 | sed -e '1,3d'

// muestra contenido en el archivo 01 pero elimina la primera y tercera línea

usuario215264
fuente
2
el comando sed le das eliminará las líneas 1, 2 y 3.
icarus
1
Esto elimina más de lo solicitado y no "guarda los cambios"
Jeff Schaller