Comment inverser les lignes d'un fichier texte?
-
03-07-2019 - |
Question
J'écris un petit script shell qui doit inverser les lignes d'un fichier texte. Existe-t-il une commande de filtre standard pour faire ce genre de chose?
Mon application spécifique est d'obtenir une liste d'identifiants de validation Git et de les traiter dans l'ordre inverse:
git log --pretty=oneline work...master | grep -v DEBUG: | cut -d' ' -f1 | reverse
Le mieux que j'ai proposé est d'implémenter reverse
comme ceci:
... | cat -b | sort -rn | cut -f2-
Ceci utilise cat
pour numéroter chaque ligne, puis sort
pour les trier par ordre numérique décroissant (ce qui revient à inverser le fichier dans son intégralité), puis couper
pour supprimer le numéro de ligne inutile.
Ce qui précède fonctionne pour mon application, mais peut échouer dans le cas général car cat -b
ne numérote que les lignes non vides.
Existe-t-il une meilleure façon plus générale de procéder?
La solution
Dans GNU coreutils , il y a tac (1)
Autres conseils
La réponse n’est pas 42, mais tac
.
Modifier: L'utilisation de sed
sed 'x;1!H;$!d;x'
et même plus longtemps
perl -e'print reverse<>'
Il existe une commande standard pour votre objectif:
tail -r file.txt
imprime les lignes de fichier.txt dans l'ordre inverse!
cat -b ne numérote que les lignes non vides ""
Si vous souhaitez éviter ce problème, pourquoi ne pas utiliser l'option "cat -n". numéroter toutes les lignes?
: "@(#)$Id: reverse.sh,v 1.2 1997/06/02 21:45:00 johnl Exp <*>quot;
#
# Reverse the order of the lines in each file
awk ' { printf("%d:%s\n", NR, <*>);}' $* |
sort -t: +0nr -1 |
sed 's/^[0-9][0-9]*://'
Fonctionne comme un charme pour moi ...
Semblable à l'exemple sed ci-dessus, utilisez perl - peut-être plus mémorable (en fonction du câblage de votre cerveau):
perl -e 'print reverse <>'
Dans ce cas, utilisez simplement - inverse
:
$ git log --reverse --pretty=oneline work...master | grep -v DEBUG: | cut -d' ' -f1
rev <name of your text file.txt>
Vous pouvez même faire ceci:
echo <whatever you want to type>|rev
awk '{a[i++]=<*>}END{for(;i-->0;)print a[i]}'
Plus rapide que sed
et compatible avec les périphériques intégrés tels que openwrt.