4 votes

AWK -- Comment faire un tri sélectif sur plusieurs colonnes ?

En awk, comment puis-je faire cela :

Entrée :

1  a  f  1  12  v  
2  b  g  2  10  w  
3  c  h  3  19  x  
4  d  i  4  15  y  
5  e  j  5  11  z  

Sortie souhaitée, en triant la valeur numérique à $5 :

1  a  f  2  10  w  
2  b  g  5  11  z  
3  c  h  1  12  v  
4  d  i  4  15  y  
5  e  j  3  19  x  

Note que le tri doit uniquement affectant $4 , $5 y $6 (sur la base de la valeur de $5 ), dans lequel la partie précédente du tableau reste intacte.

5voto

Cela peut être fait en plusieurs étapes avec l'aide de paste :

$ gawk '{print $1, $2, $3}' in.txt > a.txt
$ gawk '{print $4, $5, $6}' in.txt | sort -k 2 -n b.txt > b.txt
$ paste -d' ' a.txt b.txt
1 a f 2 10 w
2 b g 5 11 z
3 c h 1 12 v
4 d i 4 15 y
5 e j 3 19 x

4voto

Steve Points 18420

Personnellement, je trouve qu'utiliser awk pour trier en toute sécurité des tableaux de colonnes est plutôt délicat, car vous devrez souvent conserver et trier sur des clés dupliquées. Si vous avez besoin de trier sélectivement un groupe de colonnes, j'appellerais la fonction paste pour obtenir de l'aide :

paste -d ' ' <(awk '{ print $1, $2, $3 }' file.txt) <(awk '{ print $4, $5, $6 | "sort -k 2" }' file.txt)

Résultats :

1 a f 2 10 w
2 b g 5 11 z
3 c h 1 12 v
4 d i 4 15 y
5 e j 3 19 x

4voto

ghoti Points 14996

Ce site peut se faire en pure awk mais comme @steve l'a dit, ce n'est pas l'idéal. gawk a des fonctions de tri limitées, et awk n'a pas de tri intégré. Ceci dit, voici une solution (plutôt bricolée) qui utilise une fonction de comparaison dans le fichier gawk :

[ghoti@pc ~/tmp3]$ cat text 
1  a  f  1  12  v  
2  b  g  2  10  w  
3  c  h  3  19  x  
4  d  i  4  15  y  
5  e  j  5  11  z  
[ghoti@pc ~/tmp3]$ cat doit.gawk 
### Function to be called by asort().
function cmp(i1,v1,i2,v2) {
  split(v1,a1); split(v2,a2);
  if (a1[2]>a2[2])      { return 1; }
  else if (a1[2]<a2[2]) { return -1; }
  else                  { return 0; }
}

### Left-hand-side and right-hand-side, are sorted differently.
{
  lhs[NR]=sprintf("%s %s %s",$1,$2,$3);
  rhs[NR]=sprintf("%s %s %s",$4,$5,$6);
}

END {
  asort(rhs,sorted,"cmp");    ### This calls the function we defined, above.
  for (i=1;i<=NR;i++) {       ### Step through the arrays and reassemble.
    printf("%s %s\n",lhs[i],sorted[i]);
  }
}    
[ghoti@pc ~/tmp3]$ gawk -f doit.gawk text 
1 a f 2 10 w
2 b g 5 11 z
3 c h 1 12 v
4 d i 4 15 y
5 e j 3 19 x
[ghoti@pc ~/tmp3]$ 

Cela permet de conserver l'ensemble de votre fichier d'entrée dans des tableaux, de sorte que les lignes peuvent être réassemblées après le tri. Si votre fichier d'entrée contient des millions de lignes, cela peut être problématique.

Notez que vous pourriez vouloir jouer avec le printf y sprintf pour définir les séparateurs de champs de sortie appropriés.

Vous trouverez de la documentation sur l'utilisation de asort() avec des fonctions dans la page de manuel de gawk ; recherchez PROCINFO["sorted_in"] .

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