linux - script - ¿Cómo puedo eliminar el último carácter de un archivo en Unix?
script para borrar archivos en linux (8)
Aquí hay otro usando
ex
, que no encuentro tan críptico como la solución sed:
printf ''%s/n'' ''$'' ''s/.$//'' wq | ex somefile
El
$
va a la última línea, el
s
elimina el último carácter, y
wq
es el conocido (para los usuarios de vi) escribir + salir.
Digamos que tengo un archivo de texto arbitrario de varias líneas:
sometext
moretext
lastline
¿Cómo puedo eliminar solo el último carácter (la e, no la nueva línea o nulo) del archivo sin invalidar el archivo de texto?
Después de un montón de jugar con diferentes estrategias (y evitar sed -i o perl), la mejor manera de hacerlo fue con:
sed ''$! { P; D; }; s/.$//'' somefile
Si el objetivo es eliminar el último personaje en la última línea, este
awk
debería hacer:
awk ''{a[NR]=$0} END {for (i=1;i<NR;i++) print a[i];sub(/.$/,"",a[NR]);print a[NR]}'' file
sometext
moretext
lastlin
Almacena todos los datos en una matriz, luego los imprime y cambia la última línea.
Solo un comentario: sed eliminará temporalmente el archivo. Entonces, si está siguiendo el archivo, recibirá una advertencia de "No existe tal archivo o directorio" hasta que vuelva a emitir el comando de cola.
Un enfoque más simple ( salidas a stdout , no actualiza el archivo de entrada):
sed ''$ s/.$//'' somefile
-
$
es una dirección Sed que coincide solo con la última línea de entrada, lo que hace que la siguiente llamada de función (s/.$//
) se ejecute solo en la última línea. -
s/.$//
reemplaza el último carácter en la línea (en este caso la última ) con una cadena vacía; es decir, elimina efectivamente el último carácter. (antes de la nueva línea) en la línea.
.
coincide con cualquier carácter en la línea, y luego con$
ancla el partido hasta el final de la línea; observe cómo el uso de$
en esta expresión regular está relacionado conceptualmente, pero es técnicamente distinto del uso anterior de$
como dirección Sed. -
Ejemplo con entrada stdin (supone Bash, Ksh o Zsh):
$ sed ''$ s/.$//'' <<< $''line one/nline two'' line one line tw
Para actualizar el archivo de entrada también (no lo use si el archivo de entrada es un enlace simbólico):
sed -i ''$ s/.$//'' somefile
Nota:
* En OSX, tendría que usar
-i ''''
lugar de solo
-i
;
Para obtener una descripción general de las dificultades asociadas con
-i
, consulte la mitad inferior de
mi respuesta aquí
.
* Si necesita procesar archivos de entrada muy grandes y / o el rendimiento / uso del disco son una preocupación
y
está utilizando las utilidades
GNU
(Linux), consulte
la útil respuesta de sorontar
.
sed ''s/.$//'' filename | tee newFilename
Esto debería hacer tu trabajo.
RESPUESTA EDITADA
Creé un script y puse el texto dentro de mi escritorio. este archivo de prueba se guarda como "old_file.txt"
sometext
moretext
lastline
Luego escribí un pequeño script para tomar el archivo antiguo y eliminar el último carácter en la última línea.
#!/bin/bash
no_of_new_line_characters=`wc ''/root/Desktop/old_file.txt''|cut -d '' '' -f2`
let "no_of_lines=no_of_new_line_characters+1"
sed -n 1,"$no_of_new_line_characters"p ''/root/Desktop/old_file.txt'' > ''/root/Desktop/my_new_file''
sed -n "$no_of_lines","$no_of_lines"p ''/root/Desktop/old_file.txt''|sed ''s/.$//g'' >> ''/root/Desktop/my_new_file''
Al abrir el nuevo_archivo que creé, mostré el resultado de la siguiente manera:
sometext
moretext
lastlin
Pido disculpas por mi respuesta anterior (no estaba leyendo con cuidado)
truncate
truncate -s-1 file
Elimina un carácter (-1) del final del mismo archivo.
Exactamente como
>>
agregará al mismo archivo.
El problema con este enfoque es que no conserva una nueva línea final si existiera.
La solucion es:
if [ -n "$(tail -c1 file)" ] # if the file has not a trailing new line.
then
truncate -s-1 file # remove one char as the question request.
else
truncate -s-2 file # remove the last two characters
echo "" >> file # add the trailing new line back
fi
Esto funciona porque la cola toma el último byte (no char).
Casi no lleva tiempo incluso con archivos grandes.
¿Por qué no
sed
El problema con una solución sed como
sed ''$ s/.$//'' file
es que primero lee todo el archivo (tarda mucho tiempo con archivos grandes), luego necesita un archivo temporal (del mismo tamaño que el original ):
sed ''$ s/.$//'' file > tempfile
rm file; mv tempfile file
Y luego mueva el archivo temporal para reemplazar el archivo.