Come posso rimuovere l'ultimo separatore virgola dalla fine di un file?


9

Come può rimuovere l'ultimo separatore virgola da un file su Linux?

Esempio di file:

"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",

risultati aspettati:

"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"

Risposte:


22

Usando GNU sed:

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

Cioè, sull'ultima riga ( $) sostituire ( s) la virgola alla fine della riga ( ,$) per niente.

La modifica verrà effettuata sul posto a causa della -ibandiera.

Con standard sed:

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

Nota: qualcuno ha suggerito una modifica per cambiare "sull'ultima riga" in "ultima sulla riga" (o qualcosa di simile). Questo è sbagliato. Quando $viene utilizzato per specificare un indirizzo (una riga in cui applicare un comando di modifica), si riferisce all'ultima riga del flusso o del file. Questo è diverso dall'uso $in un'espressione regolare.


6

Per la modifica sul posto è possibile utilizzare ed, per comodità, imposta la posizione sull'ultima riga per impostazione predefinita all'apertura, quindi non è necessario affrontare esplicitamente l'ultima riga:

ed file
s/,$//
wq

O, come one-liner

printf 's/,$//\nwq\n' | ed -s file

2
In bash puoi fare a meno printfdi questo: ed -s file <<< $'s/,$//\nwq\n'(la parola chiave per la ricerca nel manuale di bash è "qui stringa").
Ruslan,

5

In generale, probabilmente sceglierei la sedsoluzione semplice . Tuttavia, se i tuoi file di input sono enormi, potresti desiderare una soluzione che non richieda il tempo di leggere l'intero file solo per modificare l'ultimo paio di byte.

Se sei sicuro al 100% che il tuo file di input termina con una virgola seguita da una nuova riga, puoi usare truncateper eliminare questi ultimi due caratteri, quindi aggiungere nuovamente una nuova riga finale:

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

Questo presuppone una distro che include GNU troncato o equivalente.


@ StéphaneChazelas sottolinea che GNU truncateora supporta truncate -s -2 filel'accorciamento del file di due byte ; se si dispone di questa versione, quanto sopra semplifica a:

truncate --size -2 lastcomma.txt
echo >> lastcomma.txt 

... e un filesystem che supportatruncate
malat

@malat, quale file system non supporta il troncamento?
Stéphane Chazelas il

@ StéphaneChazelas Giusto, questo è mal formulato. Che ne dici di [...] e un filesystem che supporta file sparsi per avere un efficiente truncate. L'OP descrive la sua soluzione a partire da: "se i tuoi file di input sono enormi" ... da qui il mio commento.
malat,

2
GNU truncateora supporta truncate -s -2 filel'accorciamento del file di due byte. Si desidera utilizzare stat -Lcome per i collegamenti simbolici, si desidera la dimensione della destinazione del collegamento simbolico (o semplicemente size=$(wc -c < file)).
Stéphane Chazelas il

2
@malat, non è necessario il supporto dei file sparsi per troncare i file. Qui, stiamo eliminando i dati dalla fine del file.
Stéphane Chazelas il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.