¿Cómo puedo eliminar el último separador de coma del final de un archivo?

9

¿Cómo se puede eliminar el último separador de coma de un archivo en Linux?

Ejemplo de archivo:

"is_supported_kafka_ranger" : "true",
"kafka_log_dir" : "/var/log/kafka",
"kafka_pid_dir" : "/var/run/kafka",
"kafka_user" : "kafka",
"kafka_user_nofile_limit" : "128000",
"kafka_user_nproc_limit" : "65536",

Resultados previstos:

"is_supported_kafka_ranger" : "true",
"kafka_log_dir" : "/var/log/kafka",
"kafka_pid_dir" : "/var/run/kafka",
"kafka_user" : "kafka",
"kafka_user_nofile_limit" : "128000",
"kafka_user_nproc_limit" : "65536"
yael
fuente

Respuestas:

22

Usando GNU sed:

sed -i '$s/,$//' file

Es decir, en la última línea ( $) sustituya ( s) la coma al final de la línea ( ,$) por nada.

El cambio se realizará en el lugar debido a la -ibandera.

Con estándar sed:

sed '$s/,$//' <file >file.new &&
mv file.new file

Nota: Alguien sugirió una edición para cambiar "en la última línea" a "última en la línea" (o algo similar). Esto está mal. Cuando $se usa para especificar una dirección (una línea donde aplicar un comando de edición), se refiere a la última línea de la secuencia o archivo. Esto es diferente de usar $en una expresión regular.

Kusalananda
fuente
6

Para la edición en el lugar que podría usar ed, convenientemente, establece la posición en la última línea de forma predeterminada al abrir, por lo que no necesita abordar la última línea explícitamente:

ed file
s/,$//
wq

O, como una sola línea

printf 's/,$//\nwq\n' | ed -s file
conductor de acero
fuente
2
En bash puede prescindir de printfesta manera: ed -s file <<< $'s/,$//\nwq\n'(la palabra clave para la búsqueda en el manual de bash es "aquí cadena").
Ruslan
5

En general, probablemente iría con la sedsolución directa . Sin embargo, si sus archivos de entrada son enormes, es posible que desee una solución que no tome el tiempo para leer todo el archivo solo para editar los últimos bytes.

Si está 100% seguro de que su archivo de entrada termina con una coma seguida de una nueva línea, puede usar truncatepara cortar estos dos últimos caracteres y luego volver a agregar una nueva línea final:

filesize=$(stat -L --format "%s" lastcomma.txt)
truncate --size $((filesize - 2)) lastcomma.txt 
echo >> lastcomma.txt 

Esto supone una distribución que incluye GNU truncado o equivalente.


@ StéphaneChazelas señala que GNU truncateahora admite truncate -s -2 fileacortar el archivo en dos bytes ; Si tiene esta versión, lo anterior se simplifica a:

truncate --size -2 lastcomma.txt
echo >> lastcomma.txt 
Trauma digital
fuente
... y un sistema de archivos compatibletruncate
malat
@malat, ¿qué sistema de archivos no admite truncar?
Stéphane Chazelas
@ StéphaneChazelas Correcto, esto está mal redactado. ¿Qué tal: [...] y un sistema de archivos que admite un archivo disperso para tener una eficiente truncate. El OP describe su solución comenzando con: "si sus archivos de entrada son enormes" ... de ahí mi comentario.
malat
2
GNU truncateahora admite truncate -s -2 fileacortar el archivo en dos bytes. Desea usar stat -Lcomo para enlaces simbólicos, desea el tamaño del objetivo del enlace simbólico (o simplemente size=$(wc -c < file)).
Stéphane Chazelas
2
@malat, no necesita compatibilidad con archivos dispersos para truncar archivos. Aquí, estamos recortando datos del final del archivo.
Stéphane Chazelas