web-dev-qa-db-fra.com

Suppression d'un caractère de nouvelle ligne à la fin d'un fichier

Pour supprimer toutes les nouvelles lignes que vous pourriez, dites:

tr -d '\n' < days.txt
cat days.txt | tr -d '\n'

mais comment utiliseriez-vous tr pour supprimer uniquement la nouvelle ligne à la fin/en bas d'un fichier texte?

Je ne suis pas sûr de spécifier juste le dernier.

22
user1257724

Profitez du fait que a) le caractère de nouvelle ligne se trouve à la fin du fichier et b) le caractère fait 1 octet: utilisez la commande truncate pour réduire le fichier d'un octet:

# a file with the Word "test" in it, with a newline at the end (5 characters total)
$ cat foo 
test

# a hex dump of foo shows the '\n' at the end (0a)
$ xxd -p foo
746573740a

# and `stat` tells us the size of the file: 5 bytes (one for each character)
$ stat -c '%s' foo
5

# so we can use `truncate` to set the file size to 4 bytes instead
$ truncate -s 4 foo

# which will remove the newline at the end
$ xxd -p foo
74657374
$ cat foo
test$ 

Vous pouvez également rouler le dimensionnement et les mathématiques dans une commande d'une seule ligne:

truncate -s $(($(stat -c '%s' foo)-1)) foo
24

Une solution plus simple que celle acceptée:

truncate -s -1 <<file>>

Depuis la page de manuel tronquée:

-s, --size=SIZE
    set or adjust the file size by SIZE
SIZE may also be prefixed by one of the following modifying characters:
    '+' extend by, '-' reduce by, '<' at most, '>' at least, '/' round down
    to multiple of, '%' round up to multiple of.
37

Si vous êtes sûr que le dernier caractère est une nouvelle ligne, c'est très simple:

head -c -1 days.txt

head -c -N signifie tout sauf les N derniers octets

Je pense que votre meilleur pari est Perl:

Perl -0pe 's/\n\Z//' days.txt

Le -0 oblige Perl à traiter le fichier entier comme une seule grande chaîne. Le -p lui indique d'imprimer cette chaîne après avoir exécuté le programme dessus. Et le -e dit "voici le programme à exécuter".

L'expression régulière \n\Z correspond à une nouvelle ligne, mais uniquement s'il s'agit du dernier caractère d'une chaîne. Et s/\n\Z// dit de remplacer une telle nouvelle ligne par rien du tout, en la supprimant.

La commande ci-dessus génère la nouvelle version du fichier, mais vous pouvez à la place modifier la version existante en ajoutant le -i ("in-place") option, éventuellement avec un suffixe qui sera utilisé pour nommer une copie de sauvegarde du fichier avant de le modifier:

 Perl -i.bak -0pe 's/\n\Z//' days.txt

Cette solution est sûre car si le dernier caractère est pas une nouvelle ligne, il ne sera pas touché. Les autres solutions qui suppriment simplement le dernier octet, peu importe ce qui peut corrompre un tel fichier.

12
Mark Reed

Essayez cette commande: sed '$ { /^$/ d}' days.txt

Vous pouvez le lire comme: "vérifiez si la dernière ligne est une ligne vide. Si c'est le cas supprimez cette ligne". J'ai testé avec les deux cas: d'abord avec un fichier ayant une nouvelle ligne à la fin et une autre fois avec un fichier se terminant par autre chose.

7
Lynch