web-dev-qa-db-fra.com

Comment puis-je supprimer le dernier caractère d'un fichier sous Unix?

Disons que j'ai un fichier texte multiligne arbitraire:

sometext
moretext
lastline

Comment puis-je supprimer uniquement le dernier caractère (le e, pas la nouvelle ligne ou la valeur null) du fichier sans rendre le fichier texte invalide?

53
MaxPRafferty

truncate

truncate -s-1 file

Supprime un (-1) caractère de la fin du même fichier. Exactement comme un >> sera ajouté au même fichier.

Le problème avec cette approche est qu’elle ne conserve pas de nouvelle ligne s’il existe.

La solution est:

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

Cela fonctionne car tail prend le dernier octet (pas de caractère).

Cela ne prend presque pas de temps, même avec de gros fichiers.

Pourquoi pas sed

Le problème avec une solution sed telle que sed '$ s/.$//' file est qu’il lit d’abord le fichier entier (cela prend du temps avec des fichiers volumineux), puis vous avez besoin d’un fichier temporaire (de la même taille que l’original):

sed '$ s/.$//' file  > tempfile
rm file; mv tempfile file

Puis déplacez le fichier temporaire pour remplacer le fichier. 

34
sorontar

Voici une autre utilisation de ex, que je trouve moins cryptée que la solution sed:

 printf '%s\n' '$' 's/.$//' wq | ex somefile

Le $ va à la dernière ligne, la s supprime le dernier caractère et wq est le bien connu (aux utilisateurs de vi) write + quit.

4
Jens

Si l'objectif est de supprimer le dernier caractère de la dernière ligne, cette awk devrait faire:

awk '{a[NR]=$0} END {for (i=1;i<NR;i++) print a[i];sub(/.$/,"",a[NR]);print a[NR]}' file
sometext
moretext
lastlin

Il stocke toutes les données dans un tableau, puis l'imprime et modifie la dernière ligne.

2
Jotne

Juste une remarque: sed supprimera temporairement le fichier . Ainsi, si vous réduisez le fichier, vous recevrez un avertissement "Aucun fichier ou répertoire de ce type" jusqu'à ce que vous réémettiez la commande tail.

1
Tim Chaubet

RÉPONSE RÉVISÉE

J'ai créé un script et mis votre texte à l'intérieur de mon bureau. ce fichier de test est enregistré sous "old_file.txt"

sometext
moretext
lastline

Après, j’ai écrit un petit script pour récupérer l’ancien fichier et éliminer le dernier caractère de la dernière ligne

#!/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'

ouvrant le nouveau_fichier que j'ai créé, affiche le résultat comme suit:

sometext
moretext
lastlin

Je m'excuse pour ma réponse précédente (je ne lisais pas attentivement)

1
repzero

Après tout un tas de jeux avec différentes stratégies (et en évitant sed -i ou Perl), le meilleur moyen que j'ai trouvé de faire cela était avec:

sed '$! { P; D; }; s/.$//' somefile
1
MaxPRafferty

sed 's/.$//' filename | tee newFilename

Cela devrait faire votre travail.

0
karthik339