web-dev-qa-db-fra.com

Tri de plusieurs clés avec le tri Unix

J'ai potentiellement des fichiers volumineux qui doivent être triés par les touches 1-n. Certaines de ces clés peuvent être numériques et d'autres non. Il s'agit d'un fichier colonne de largeur fixe, il n'y a donc pas de délimiteur.

Y at-il un bon moyen de faire cela avec le type Unix? Avec une clé, c'est aussi simple que d'utiliser '-n'. J'ai lu la page de manuel et cherché brièvement dans Google, mais je n'ai pas trouvé de bon exemple. Comment pourrais-je m'y prendre pour accomplir cela?

Remarque: j'ai exclu Perl en raison du potentiel de taille du fichier. Ce serait un dernier recours.

128
Chris Kloberdanz

Utilisez le -k option (ou --key=POS1[,POS2]). Il peut apparaître plusieurs fois et chaque clé peut avoir des options globales (telles que n pour le tri numérique)

68
Ken Gentle

Attention cependant:

Si vous voulez trier le fichier principalement par le champ 3 et secondairement par le champ 2, vous ne voulez pas ceci:

sort -k 3 -k 2 < inputfile

vous voulez cela à la place:

sort -k 3,3 -k 2,2 < inputfile

Le premier trie le fichier par la chaîne du début du champ 3 à la fin de la ligne (potentiellement unique).

-k, --key=POS1[,POS2]     start a key at POS1 (Origin 1), end it at POS2
                          (default end of line)
298
andras

L'option -k est ce que vous voulez.

-k 1.4,1.5n -k 1.14,1.15n

Utiliserait les positions de caractères 4 à 5 dans le premier champ (il s'agit d'un seul champ à largeur fixe) et trier numériquement la première clé.

La deuxième clé serait également les caractères 14-15 dans le premier champ.

(modifier)

Exemple (tout ce que j'ai sous la main est pratique sous DOS/cygwin):

dir | \cygwin\bin\sort.exe -k 1.4,1.5n -k 1.40,1.60r

pour les données:

12/10/2008  01:10 PM         1,564,990 outfile.txt

Trie le listing du répertoire par numéro de mois (pos 4-5) numériquement, puis par nom de fichier (pos 40-60) en sens inverse. Puisqu'il n'y a pas d'onglets, c'est tout le champ 1 à trier.

92
Clinton Pierce

En voici une pour trier les différentes colonnes d’un fichier csv par ordre numérique et dans le dictionnaire, les colonnes 5 et suivantes dans l’ordre du dictionnaire

~/test>sort -t, -k1,1n -k2,2n -k3,3d -k4,4n -k5d  sort.csv
1,10,b,22,Ga
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C

~/test>cat sort.csv
2,3,a,9,C
2,2,b,20,F
2,2,c,19,Gb,hj
2,2,c,19,Gb,hi
2,2,c,19,Ga
2,2,b,22,Ga
1,10,b,22,Ga

Notez que -k1,1n signifie numérique commençant par la colonne 1 et se terminant par la colonne 1. Si j'avais fait ce qui suit, il aurait concaténé les colonnes 1 et 2, ce qui ferait 1,10 trié par 110

~/test>sort -t, -k1,2n -k3,3 -k4,4n -k5d  sort.csv
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C
1,10,b,22,Ga
21
edW

Je crois dans ton cas quelque chose comme

sort -t@ -k1.1,1.4 -k1.5,1.7 ... <inputfile

travaillera mieux. @ est le séparateur de champ, assurez-vous que c'est un caractère qui n'apparaît nulle part. alors votre entrée est considérée comme composée d'une colonne.

Edit: apparemment Clintp a déjà donné une réponse similaire, désolé. Comme il le fait remarquer, les drapeaux 'n' et 'r' peuvent être ajoutés à chaque option -k ....

11
Dong Hoon

Notez que vous pouvez également vouloir stabiliser le tri avec le -s _ switch, de sorte que les lignes de même rang conservent également leur ordre relatif initial dans la sortie.

5
ron

Je veux juste ajouter quelques astuces. Lorsque vous utilisez sort, faites attention à vos paramètres régionaux, ce qui affecte l'ordre de la comparaison des clés. J'utilise généralement explicitement LC_ALL = C pour créer les paramètres régionaux que je veux.

2
jianpx