una - Eliminar la última línea de un archivo en Bash




sed reemplazar/ (8)

Usuarios de Mac

Si solo desea que la última línea elimine la salida sin cambiar el archivo, haga

sed -e '$ d' foo.txt

Si desea eliminar la última línea del archivo de entrada, haga

sed -i '' -e '$ d' foo.txt

Tengo un archivo, foo.txt , que contiene las siguientes líneas:

a
b
c

Quiero un comando simple que foo.txt como resultado que el contenido de foo.txt sea:

a
b

Para usuarios de Mac:

En Mac, la cabeza -n -1 no funciona. Y, estaba tratando de encontrar una solución simple [sin preocuparme por el tiempo de procesamiento] para resolver este problema solo con los comandos "cabeza" y / o "cola".

Intenté la siguiente secuencia de comandos y me alegré de poder resolverlo simplemente usando el comando "tail" [con las opciones disponibles en Mac]. Entonces, si estás en Mac y quieres usar solo "cola" para resolver este problema, puedes usar este comando:

cat file.txt | cola -r | cola -n +2 | cola -r

Explicación:

1> cola -r: simplemente invierte el orden de las líneas en su entrada

2> cola -n +2: esto imprime todas las líneas a partir de la segunda línea en su entrada


Esta es, con mucho, la solución más rápida y sencilla, especialmente en archivos grandes:

head -n -1 foo.txt > temp.txt ; mv temp.txt foo.txt

Si quieres borrar la línea superior usa esto:

tail -n +2 foo.txt

lo que significa líneas de salida a partir de la línea 2.

No use sed para eliminar líneas de la parte superior o inferior de un archivo; es muy lento si el archivo es grande.


Para eliminar la última línea de un archivo sin leer todo el archivo o reescribir nada , puede usar

tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{}

Para eliminar la última línea y también imprimirla en la salida estándar ("pop"), puede combinar ese comando con tee :

tail -n 1 "$file" | tee >(wc -c | xargs -I {} truncate "$file" -s -{})

Estos comandos pueden procesar eficientemente un archivo muy grande. Esto es similar e inspirado por la respuesta de Yossi, pero evita el uso de algunas funciones adicionales.

Si va a usar estos repetidamente y desea controlar los errores y algunas otras funciones, puede usar el comando poptail aquí: https://github.com/donm/evenmoreutils


Tuve problemas con todas las respuestas aquí porque estaba trabajando con un archivo ENORME (~ 300Gb) y ninguna de las soluciones se amplió. Aquí está mi solución:

dd if=/dev/null of=<filename> bs=1 seek=$(echo $(stat --format=%s <filename> ) - $( tail -n1 <filename> | wc -c) | bc )

En palabras: Averigüe la longitud del archivo con el que desea terminar (longitud del archivo menos longitud de la longitud de su última línea, usando bc ) y, establezca esa posición para que sea el final del archivo (al dd un byte de /dev/null en él).

Esto es rápido porque la tail comienza a leer desde el final, y dd sobrescribirá el archivo en su lugar en lugar de copiar (y analizar) cada línea del archivo, que es lo que hacen las otras soluciones.

NOTA: ¡Esto elimina la línea del archivo en su lugar! Haga una copia de seguridad o pruebe un archivo ficticio antes de probarlo en su propio archivo.


Usando GNU sed :

sed -i '$ d' foo.txt

La opción -i no existe en las versiones GNU sed anteriores a 3.95, por lo que debe usarla como filtro con un archivo temporal:

cp foo.txt foo.txt.tmp
sed '$ d' foo.txt.tmp > foo.txt
rm -f foo.txt.tmp

Por supuesto, en ese caso también puedes usar head -n -1 lugar de sed .


awk 'NR>1{print buf}{buf = $0}'

Esencialmente, este código dice lo siguiente:

Para cada línea después de la primera, imprima la línea en buffer

Para cada línea, reinicie el búfer.

El búfer está retrasado por una línea, por lo que termina imprimiendo las líneas 1 a n-1


echo -e '$d\nw\nq'| ed foo.txt




truncate