Comment supprimer le dernier séparateur de virgules à la fin d'un fichier?

9

Comment supprimer le dernier séparateur de virgules d'un fichier sous Linux?

Exemple de fichier:

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

Résultats attendus:

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

Réponses:

22

Utilisation de GNU sed:

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

Autrement dit, sur la dernière ligne ( $), remplacez ( s) la virgule à la fin de la ligne ( ,$) par rien.

Le changement se fera sur place en raison du -idrapeau.

Avec standard sed:

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

Remarque: Quelqu'un a suggéré une modification pour remplacer «sur la dernière ligne» par «dernier sur la ligne» (ou quelque chose de similaire). C'est faux. Quand $est utilisé pour spécifier une adresse (une ligne où appliquer une commande d'édition), alors il fait référence à la dernière ligne du flux ou du fichier. C'est différent de l'utilisation $dans une expression régulière.

Kusalananda
la source
6

Pour l'édition sur place, vous pouvez utiliser ed- commodément, il définit la position sur la dernière ligne par défaut à l'ouverture, vous n'avez donc pas besoin de traiter la dernière ligne explicitement:

ed file
s/,$//
wq

Ou, en une ligne

printf 's/,$//\nwq\n' | ed -s file
tournevis
la source
2
En bash, vous pouvez vous passer de printfceci: ed -s file <<< $'s/,$//\nwq\n'(le mot-clé de recherche dans le manuel bash est "ici chaîne").
Ruslan
5

En général, j'irais probablement avec la sedsolution simple . Cependant, si vos fichiers d'entrée sont volumineux, vous voudrez peut-être une solution qui ne prend pas le temps de lire l'intégralité du fichier juste pour modifier les deux derniers octets.

Si vous êtes sûr à 100% que votre fichier d'entrée se termine par une virgule suivie d'une nouvelle ligne, vous pouvez utiliser truncatepour couper ces deux derniers caractères, puis ré-ajouter une nouvelle ligne finale:

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

Cela suppose une distribution qui inclut GNU tronqué ou équivalent.


@ StéphaneChazelas souligne que GNU truncatesupporte désormais truncate -s -2 filede raccourcir le fichier de deux octets ; si vous avez cette version, ce qui précède se simplifie pour:

truncate --size -2 lastcomma.txt
echo >> lastcomma.txt 
Traumatisme numérique
la source
... et un système de fichiers qui prend en chargetruncate
malat
@malat, quel système de fichiers ne prend pas en charge tronquer?
Stéphane Chazelas
@ StéphaneChazelas C'est vrai, c'est mal formulé. Que diriez-vous: [...] et un système de fichiers qui prend en charge un fichier clairsemé pour avoir une efficacité truncate. L'OP décrit sa solution en commençant par: "si vos fichiers d'entrée sont énormes" ... d'où mon commentaire.
malat
2
GNU truncateprend désormais en charge la truncate -s -2 fileréduction du fichier de deux octets. Vous souhaitez utiliser stat -Lcomme pour les liens symboliques, vous voulez la taille de la cible du lien symbolique (ou simplement size=$(wc -c < file)).
Stéphane Chazelas
2
@malat, vous n'avez pas besoin de la prise en charge de fichiers clairsemés pour tronquer les fichiers. Ici, nous supprimons les données à la fin du fichier.
Stéphane Chazelas