Ordre de ligne inverse sauf en-tête

Avec une commande shell, je veux inverser les lignes d’un fichier texte, en excluant la ligne d’en-tête.

Number,Letter,Person 1,a,Alice 2,b,Bob 3,c,Claire 

devraient devenir

 Number,Letter,Person 3,c,Claire 2,b,Bob 1,a,Alice 

Je recherche à la fois une solution “en place” (changer le fichier original) et une solution de streaming (lecture du fichier original à partir de stdin et impression du résultat dans stdout).

Idéalement, la commande ou le script serait compatible avec POSIX, mais d’autres solutions pourraient également être intéressantes. Un oneliner serait bien.

Je suis également intéressé par la performance / complexité de toute solution.

Voici une commande awk pour faire ceci:

 awk '{a[NR]=$0} END{print a[1]; for (i=NR; i>1; i--) print a[i]}' file Number,Letter,Person 3,c,Claire 2,b,Bob 1,a,Alice 

Ici, a[1] représente un enregistrement d’en-tête. Les entrées restantes dans le tableau associatif a représentent les lignes avec l’index en tant que numéro d’enregistrement.

Alternativement, en utilisant la head, tail, cat :

 { head -1 f && tail -n +2 file | tac; } > file._tmp && mv file._tmp file Number,Letter,Person 3,c,Claire 2,b,Bob 1,a,Alice 

Avec GNU sed:

 sed -n '1p;2h;3,${G;h};$p' file 

Sortie:

 Nombre, lettre, personne
 3, c, Claire
 2, b, Bob
 1, a, Alice

Si vous voulez éditer votre fichier “in place”, utilisez l’option -i sed.


Voir: man sed

 $ awk -v OFS='\t' '{print (NR==1), NR, $0}' file | sort -snr -k1 -k2 | cut -f3- Number,Letter,Person 3,c,Claire 2,b,Bob 1,a,Alice