Tengo un archivo que foo.txt
contiene las siguientes líneas:
a
b
c
Quiero un comando simple que resulte en el contenido de foo.txt
ser:
a
b
Tengo un archivo que foo.txt
contiene las siguientes líneas:
a
b
c
Quiero un comando simple que resulte en el contenido de foo.txt
ser:
a
b
Respuestas:
Utilizando GNU sed
:
sed -i '$ d' foo.txt
La -i
opción no existe en GNU sed
versiones 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 podría usar en head -n -1
lugar de sed
.
Mac OS:
En Mac OS X (a partir de 10.7.4), el equivalente del sed -i
comando anterior es
sed -i '' -e '$ d' foo.txt
$ d
una expresión regular. Es un comando sed. d
es el comando para eliminar una línea, mientras que $
significa "la última línea del archivo". Al especificar una ubicación (llamada "rango" en la jerga sed) antes de un comando, ese comando solo se aplica a la ubicación especificada. Entonces, este comando dice explícitamente "en el rango de la última línea de un archivo, elimínelo". Muy hábil y directo al grano, si me preguntas.
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 desea eliminar la línea superior, use esto:
tail -n +2 foo.txt
lo que significa líneas de salida que comienzan en la línea 2.
No lo use sed
para eliminar líneas de la parte superior o inferior de un archivo; es muy lento si el archivo es grande.
head -n -1 foo.txt
es suficiente
brew install coreutils
(utilidades principales de GNU) y usar en ghead
lugar de head
.
FILE=$1; TAIL=$2; head -n -${TAIL} ${FILE} > temp ; mv temp ${FILE}
Ejecútelo para eliminar 4 líneas, por ejemplo, de myfile como: ./TAILfixer myfile 4
por supuesto, primero chmod +x TAILfixer
sed
, este comando también es bastante lento
Tuve problemas con todas las respuestas aquí porque estaba trabajando con un archivo ENORME (~ 300Gb) y ninguna de las soluciones se ajustó. 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: descubra la longitud del archivo con el que desea terminar (longitud del archivo menos la longitud de su última línea, usando bc
) y configure esa posición para que sea el final del archivo ( dd
ingresando un byte de /dev/null
a eso).
Esto es rápido porque tail
comienza a leer desde el final y dd
sobrescribirá el archivo en su 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 en un archivo ficticio antes de probarlo en su propio archivo!
Para eliminar la última línea de un archivo sin leer el archivo completo 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 stdout ("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 usarlos repetidamente y desea manejar errores y algunas otras funciones, puede usar el poptail
comando aquí:
https://github.com/donm/evenmoreutils
truncate
no está disponible en OS X por defecto. Pero es fácil de instalar con Brew: brew install truncate
.
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
-i ''
le dice a sed que modifique el archivo en el lugar, mientras mantiene una copia de seguridad en un archivo con la extensión provista como parámetro. Como el parámetro es una cadena vacía, no se crea ningún archivo de respaldo. -e
le dice a sed que ejecute un comando. El comando $ d
significa: buscar la última línea ( $
) y eliminarla ( d
).
En Mac, head -n -1 no funcionará. Y estaba tratando de encontrar una solución simple [sin preocuparme por el tiempo de procesamiento] para resolver este problema solo usando los comandos "head" y / o "tail".
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á en Mac y desea usar solo "cola" para resolver este problema, puede usar este comando:
cat file.txt | cola -r | cola -n +2 | cola -r
1> tail -r: simplemente invierte el orden de las líneas en su entrada
2> tail -n +2: imprime todas las líneas que comienzan desde la segunda línea en su entrada
ghead -n -1
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 almacenada
para cada línea, reinicie el búfer
El búfer está retrasado por una línea, por lo tanto, termina imprimiendo las líneas 1 a n-1
awk "NR != `wc -l < text.file`" text.file |> text.file
Este fragmento hace el truco.
Ambas soluciones están aquí en otras formas. Encontré esto un poco más práctico, claro y útil:
Usando dd:
BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
dd if=${ORIGINALFILE} of=${ORIGINALFILE}.tmp status=none bs=1 count=$(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc )
/bin/mv -f ${ORIGINALFILE}.tmp ${ORIGINALFILE}
Usando truncar:
BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
truncate -s $(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc ) ${ORIGINALFILE}
sed '$d' ~/path/to/your/file/name
sed -i '' -e '$ d' ~/path/to/your/file/name
Así es como puede hacerlo manualmente (yo personalmente uso mucho este método cuando necesito eliminar rápidamente la última línea de un archivo):
vim + [FILE]
Ese +
signo allí significa que cuando el archivo se abre en el editor de texto vim, el cursor se colocará en la última línea del archivo.
Ahora solo presione d
dos veces en su teclado. Esto hará exactamente lo que desea: eliminar la última línea. Después de eso, presione :
seguido de x
y luego presione Enter
. Esto guardará los cambios y lo llevará de regreso al shell. Ahora, la última línea se ha eliminado con éxito.
sed -i
comando anterior essed -i '' -e '$ d' foo.txt
. Además,head -n -1
actualmente no funcionará en una Mac.