150 votes

Existe-t-il un moyen d'ignorer les lignes d'en-tête dans un tri UNIX ?

J'ai un fichier à champs de largeur fixe que j'essaie de trier à l'aide de l'utilitaire de tri UNIX (Cygwin, dans mon cas).

Le problème est qu'il y a un en-tête de deux lignes en haut du fichier qui est trié en bas du fichier (car chaque ligne d'en-tête commence par un deux-points).

Existe-t-il un moyen de dire à sort de "laisser passer les deux premières lignes sans les trier" ou de spécifier un ordre qui trie les deux lignes en haut - les lignes restantes commencent toujours par un chiffre à 6 chiffres (qui est en fait la clé sur laquelle je trie) si cela peut aider.

Exemple :

:0:12345
:1:6:2:3:8:4:2
010005TSTDOG_FOOD01
500123TSTMY_RADAR00
222334NOTALINEOUT01
477821USASHUTTLES21
325611LVEANOTHERS00

devrait être triée :

:0:12345
:1:6:2:3:8:4:2
010005TSTDOG_FOOD01
222334NOTALINEOUT01
325611LVEANOTHERS00
477821USASHUTTLES21
500123TSTMY_RADAR00

5voto

Vijay Points 17992
head -2 <your_file> && nawk 'NR>2' <your_file> | sort

exemple :

> cat temp
10
8
1
2
3
4
5
> head -2 temp && nawk 'NR>2' temp | sort -r
10
8
5
4
3
2
1

3voto

Ian Sherbin Points 41

Il suffit de 2 lignes de code...

head -1 test.txt > a.tmp; 
tail -n+2 test.txt | sort -n >> a.tmp;

Pour une donnée numérique, -n est nécessaire. Pour un tri alpha, le -n n'est pas requis.

Exemple de fichier :
$ cat test.txt

en-tête
8
5
100
1
-1

Résultat :
$ cat a.tmp

en-tête
-1
1
5
8
100

3voto

flu Points 356

Voici donc une fonction bash où les arguments sont exactement comme sort. Fichiers et tuyaux de soutien.

function skip_header_sort() {
    if [[ $# -gt 0 ]] && [[ -f ${@: -1} ]]; then
        local file=${@: -1}
        set -- "${@:1:$(($#-1))}"
    fi
    awk -vsargs="$*" 'NR<2{print; next}{print | "sort "sargs}' $file
}

Comment cela fonctionne. Cette ligne vérifie s'il y a au moins un argument et si le dernier argument est un fichier.

    if [[ $# -gt 0 ]] && [[ -f ${@: -1} ]]; then

Cela permet de sauvegarder le fichier dans un argument séparé. Comme nous sommes sur le point d'effacer le dernier argument.

        local file=${@: -1}

Ici, nous supprimons le dernier argument. Puisque nous ne voulons pas le passer comme un argument de tri.

        set -- "${@:1:$(($#-1))}"

Enfin, nous faisons la partie awk, en passant les arguments (moins le dernier argument si c'était le fichier) à sort dans awk. Ceci a été suggéré à l'origine par Dave, et modifié pour prendre les arguments de sort. Nous nous appuyons sur le fait que $file sera vide si nous sommes en tuyauterie, donc ignorée.

    awk -vsargs="$*" 'NR<2{print; next}{print | "sort "sargs}' $file

Exemple d'utilisation avec un fichier séparé par des virgules.

$ cat /tmp/test
A,B,C
0,1,2
1,2,0
2,0,1

# SORT NUMERICALLY SECOND COLUMN
$ skip_header_sort -t, -nk2 /tmp/test
A,B,C
2,0,1
0,1,2
1,2,0

# SORT REVERSE NUMERICALLY THIRD COLUMN
$ cat /tmp/test | skip_header_sort -t, -nrk3
A,B,C
0,1,2
2,0,1
1,2,0

0voto

JonDeg Points 151

Voici une fonction du shell bash dérivée des autres réponses. Elle gère à la fois les fichiers et les pipes. Le premier argument est le nom du fichier ou '-' pour stdin. Les autres arguments sont passés à sort. Quelques exemples :

$ hsort myfile.txt
$ head -n 100 myfile.txt | hsort -
$ hsort myfile.txt -k 2,2 | head -n 20 | hsort - -r

La fonction shell :

hsort ()
{
   if [ "$1" == "-h" ]; then
       echo "Sort a file or standard input, treating the first line as a header.";
       echo "The first argument is the file or '-' for standard input. Additional";
       echo "arguments to sort follow the first argument, including other files.";
       echo "File syntax : $ hsort file [sort-options] [file...]";
       echo "STDIN syntax: $ hsort - [sort-options] [file...]";
       return 0;
   elif [ -f "$1" ]; then
       local file=$1;
       shift;
       (head -n 1 $file && tail -n +2 $file | sort $*);
   elif [ "$1" == "-" ]; then
       shift;
       (read -r; printf "%s\n" "$REPLY"; sort $*);
   else
       >&2 echo "Error. File not found: $1";
       >&2 echo "Use either 'hsort <file> [sort-options]' or 'hsort - [sort-options]'";
       return 1 ;
   fi
}

0voto

Bik Points 1

C'est la même chose que la réponse de Ian Sherbin mais ma mise en œuvre est :-.

cut -d'|' -f3,4,7 $arg1 | uniq > filetmp.tc
head -1 filetmp.tc > file.tc;
tail -n+2 filetmp.tc | sort -t"|" -k2,2 >> file.tc;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X