sortinger mais garder la ligne d'en-tête en haut

J'obtiens la sortie d'un programme qui produit d'abord une ligne qui est un groupe d'en-têtes de colonne, puis un set de lignes de données. Je veux couper plusieurs colonnes de cette sortie et la voir sortingée en fonction de différentes colonnes. Sans les en-têtes, la découpe et le sorting sont facilement accomplis via l'option -k pour sort avec cut ou awk pour voir un sous-set des colonnes. Cependant, cette méthode de sorting mélange les en-têtes de colonne avec le rest des lignes de sortie. Y a-t-il un moyen facile de garder les en-têtes au sumt?

    Voler l'idée d'Andy et en faire une fonction donc c'est plus facile à utiliser:

     # print the header (the first line of input) # and then run the specified command on the body (the rest of the input) # use it in a pipeline, eg ps | body grep somepattern body() { IFS= read -r header printf '%s\n' "$header" "$@" } 

    Maintenant, je peux faire:

     $ ps -o pid,comm | body sort -k2 PID COMMAND 24759 bash 31276 bash 31032 less 31177 less 31020 man 31167 man ... $ ps -o pid,comm | body grep less PID COMMAND 31032 less 31177 less 

    Vous pouvez garder l'en-tête au sumt comme ceci avec bash:

     command | (read -r; printf "%s\n" "$REPLY"; sort) 

    Ou le faire avec perl:

     command | perl -e 'print scalar (<>); print sort { ... } <>' 

    J'ai trouvé une belle version awk qui fonctionne bien dans les scripts:

     awk 'NR == 1; NR > 1 {print $0 | "sort -n"}' 

    Hackish mais efficace: ajoutez 0 à toutes les lignes d'en-tête et 1 à toutes les autres lignes avant de les sortinger. Ssortingp le premier caractère après le sorting.

     … | awk '{print (NR <= 2 ? "0 " : "1 ") $0}' | sort -k 1 -k… | cut -b 3- 

    Voici un peu de bruit de ligne perl que vous pouvez faire passer votre sortie pour tout sortinger mais gardez la première ligne en haut: perl -e 'print scalar <>, sort <>;'

    Simple et direct!

     <command> | head -n 1; <command> | sed 1d | sort <....> 
    • sed nd —> 'n' spécifie le numéro de ligne et 'd' signifie supprimer.

    Je pense que c'est le plus facile.

     ps -ef | ( head -1 ; sort ) 

    ou ce qui est peut-être plus rapide car il ne crée pas de sous-shell

     ps -ef | { head -1 ; sort ; } 

    Autres utilisations cool

    mélanger les lignes après la rangée d'en-tête

     cat file.txt | ( head -1 ; shuf ) 

    Inverser les lignes après la ligne d'en-tête

     cat file.txt | ( head -1 ; tac ) 
     command | head -1; command | tail -n +2 | sort 

    J'ai essayé la command | {head -1; sort; } command | {head -1; sort; } command | {head -1; sort; } solution et peut confirmer qu'il fait vraiment les choses en place – la head lit sur plusieurs lignes du tuyau, puis ne sort que le premier. Donc, le rest de la sortie, cette head n'a pas lu, est passé à sort –NOT le rest de la sortie à partir de la ligne 2!

    Le résultat est qu'il manque des lignes (et une ligne partielle!) Qui étaient au début de votre sortie de command (sauf que vous avez toujours la première ligne) – un fait qui est facile à confirmer en ajoutant un tuyau à wc à la fin du pipeline ci-dessus – mais il est extraordinairement difficile de tracer si vous ne le savez pas! J'ai passé au less 20 minutes à essayer de comprendre pourquoi j'avais une ligne partielle (100 premiers octets coupés) dans ma sortie avant de la résoudre.

    Ce que j'ai fini par faire, qui a fonctionné magnifiquement et n'a pas nécessité d'exécuter la command deux fois, était:

     myfile=$(mktemp) whatever command you want to run > $myfile head -1 $myfile sed 1d $myfile | sort rm $myfile 

    Si vous avez besoin de mettre la sortie dans un file, vous pouvez le modifier pour:

     myfile=$(mktemp) whatever command you want to run > $myfile head -1 $myfile > outputfile sed 1d $myfile | sort >> outputfile rm $myfile 

    Je suis venu ici à la search d'une solution pour la command w . Cette command affiche les détails de qui est connecté et ce qu'ils font.

    Pour afficher les résultats sortingés, mais avec les en-têtes gardés en haut (il y a 2 lignes d'en-têtes), je me suis fixé sur:

     w | head -n 2; w | tail -n +3 | sort 

    Évidemment, cela exécute la command w deux fois et peut donc ne pas convenir à toutes les situations. Cependant, à son avantage, il est sensiblement plus facile à retenir.

    Notez que la tail -n +3 signifie "montrer toutes les lignes à partir du 3ème" (voir la man tail pour plus de détails).