2012-08-29 28 views

Respuesta

9

(solución se basa en sch's answer modo crédito debe ir a él/ella)

Este enfoque permitirá recuperar de manera eficiente la última línea del fichero y trunca el archivo para eliminar esa línea. Esto puede tratar mejor con entradas grandes ya que el archivo no se lee de forma secuencial.

# retrieve last line from file 
LAST=$(tail -n 1 my_log_file.log) 

# truncate file 
let TRUNCATE_SIZE="${#LAST} + 1" 
truncate -s -"$TRUNCATE_SIZE" my_log_file.log 

# ... $LAST contains 'popped' last line 

Tenga en cuenta que esto no funcionará como se espera si el archivo se ha modificado entre las llamadas a tail y truncate.

+1

Tenga en cuenta que, al contrario de la solución basada en "wc" que di que funcionaría en los sistemas GNU, lo anterior solo funcionará correctamente con zsh si la última línea contiene caracteres NUL. Además, no funcionará correctamente si la última línea no tiene terminación NL. –

+0

Además, 'truncado' espera un tamaño en _bytes_, mientras que' $ {# LAST} 'calcula la longitud de' $ LAST' en número de caracteres. Querrá establecer la configuración regional en C para que sea equivalente. De lo contrario, eso no funcionaría correctamente si la última línea contiene caracteres de varios bytes. –

4

Una forma es:

sed '$d' <f1> f2 ; mv f2 f1 
+0

No entiendo esto. ¿Qué es 'f2' y' f1'? – Raptor

+0

Llegué tarde pero esta es mi solución favorita. Puede hacer el cambio in-situ usando la bandera "-i" de sed: "sed -i -e '$ d' my_log_file.log" –

+0

Tenga cuidado con el uso de '-i' si escribe scripts multiplataforma ya que diferente en macOS y Linux. – bfontaine

27

para obtener el contenido del archivo sin la última línea, puede utilizar

head -n-1 logfile.log 

(no estoy seguro de que esto es apoyado por todas partes)

o

sed '$d' logfile.log 
+0

Perfecto !!!! nice one – Satish

+1

¡El sed funciona a la perfección! $ d es el comando que se cierra antes de la última línea, ¡por eso puede omitir la última línea! Ver https://www.gnu.org/software/sed/manual/sed.html. – nothize

15

Lo que quiere es truncar el archivo justo antes de la última línea sin tener que leer el archivo por completo.

truncate -s -"$(tail -n1 file | wc -c)" file 

Suponiendo que el archivo no se está escribiendo en este momento.

truncate es parte de los coreutils de GNU (por lo general, se encuentra en las distribuciones de Linux recientes) y no es un comando estandarizado de Unix o POSIX. Muchas implementaciones "dd" se pueden usar también para truncar un archivo.

+0

El uso de 'tail' +' truncate' sería una solución más eficiente.Naturalmente, para permitir que el OP recupere el contenido de la última línea 'tail -n' debe llamarse por separado y almacenarse en una var. Luego puede usar '$ {# VAR} + 1' como tamaño de truncamiento. –

+0

Se agregó una [respuesta wiki] (http://stackoverflow.com/questions/12176492/shell-delete-thelast-line-of-a-huge-text-log-file/12176634#12176634) con los cambios propuestos. –

+3

Parece haber un extra, anterior al combo tail/wc. Además, podría usar la opción '-r' (usar el tamaño del archivo dado) aquí:' truncado -r <(cola -n1 archivo) archivo 'si no le importa el bashismo. – chepner

Cuestiones relacionadas