Trier le fichier CSV par priorité de colonne à l'aide de la commande «trier»

92

J'ai un fichier csv, et je voudrais le trier par priorité de colonne, comme "Trier par". Par exemple:

3;1;2
1;3;2
1;2;3
2;3;1
2;1;3
3;2;1

Si cette situation était le résultat d'un "select", le "order by" serait le suivant: order by column2, column1, column3 - le résultat serait:

2;1;3
3;1;2
1;2;3
3;2;1
1;3;2
2;3;1

J'aimerais savoir comment obtenir ce même résultat en utilisant la commande "sort" sous Unix.

Rafael Orágio
la source
4
Au fait, c'est un fichier ssv (valeurs séparées par des points-virgules): P
John Strood

Réponses:

154
sort --field-separator=';' --key=2,1,3
Charlie Martin
la source
8
Si les valeurs sont numériques, alors vous voudrez probablement envisager d'utiliser l' -noption qui "comparera selon la valeur numérique de la chaîne" ou l' -goption qui "comparera selon la valeur numérique générale". Une comparaison de chaînes de valeurs numériques obtiendra les nombres classés comme 1,10,2,20. Au moins, ce sont des options disponibles sur ma version de tri sur CentOS. Vous devez vérifier avec la page de manuel les options correctes sur votre version de tri.
Adam Porad
4
Je reçoissort: stray character in field spec: invalid field specification ‘2,1,3’
Martin Thoma
3
Cependant, a sort --field-separator=',' -r -k3 -k1 -k2 source.csv > target.csvfonctionné pour moi.
Martin Thoma
6
@MartinThoma ça fait longtemps mais j'ai rencontré votre problème et j'ai trouvé ça sort --field-separator=';' --key={2,1,3}. Cela a fonctionné à GNU coreutils 8.4partir d'avril 2016
mrbolichi
2
@mrbolichi la notation --key={2,1,3}utilise l'expansion d'accolades de bash
kvantour
28

Supposons que vous ayez une autre ligne 3;10;3dans votre unsorted.csvfichier. Ensuite, je suppose que vous vous attendez à un résultat trié numériquement:

2;1;3
3;1;2
1;2;3
3;2;1
1;3;2
2;3;1
3;10;3

et non triés par ordre alphabétique:

2;1;3
3;1;2
3;10;3
1;2;3
3;2;1
1;3;2
2;3;1

Pour l'obtenir, vous devez utiliser -n:

sort --field-separator=';' -n -k 2,2 -k 1,1 -k 3,3 unsorted.csv

Il convient de mentionner qu'il 2,2faut utiliser. Si seulement 2est utilisé, sortprend alors la chaîne du début du champ 2 à la fin. 2,2s'assure que seul le champ 2est utilisé.

Martin Thoma
la source
7
Le pointeur de la différence entre -k 2 et -k 2,2 est significatif! J'avais oublié cela lors de ma première lecture de la page de manuel. Merci.
usonianhorizon
J'ai ajouté quelques lignes supplémentaires, 3;10;3, 3:10:5, 3:10;2, 3;10;3dans cet ordre dans le fichier source, et lors de l' utilisation juste -k 2,2 il semble trier la colonne 2 et 3. La page de manuel dit "The -k option may be specified multiple times, in which case subsequent keys are compared when earlier keys compare equal.". Dans mon cas, la clé précédente (valeur = 10) était comparable, cependant, je n'ai pas spécifié -kplusieurs fois. Je ne sais pas s'il s'agit d'un comportement fiable ou lié à mon système (mac). En fin de compte, cela n'a pas d'importance, tant que le tri primaire est correct.
Davos
Oh je vois qu'il y a aussi -sun tri stable qui ignore les clés égales, c'est apparemment plus rapide selon l'homme.
Davos
24

La réponse de Charlie ci-dessus n'a pas fonctionné pour moi sur Cygwin (tri version 2.0, GNU textutils), ce qui suit a fonctionné:

sort -t"," -k2 -k1 -k1
Samuel Kerrien
la source
3
Cygwin a une ancienne version de sort. Comme toujours, la page de manuel est votre amie.
Charlie Martin
2
Je suis d'accord avec @CharlieMartin, vous devriez consulter la page de manuel de votre système. Sur CentOS j'ai utilisésort --field-separator=';' -k2 -k1 -k3 test.csv
Adam Porad
-6

..et si quelqu'un a suivi la solution de 'tri' mais veut maintenant obtenir plus qu'une seule entrée unique par ligne (c'est-à-dire le nombre X supérieur d'entrées uniques), une fois que vous avez trié le fichier en utilisant 'sort', vous pouvez utiliser une petite application que j'ai créée ici:

https://github.com/danieliversen/MiscStuff/blob/master/scripts/findTopUniques.java

Daniel Iversen
la source
2
Bien pour vous! Mais dans votre cas, vous pourriez avoir juste utiliser cat unsorted-file | sort | uniq | head -X- quand Xest le nombre de premières lignes que vous souhaitez afficher.
Slavik Meltser
@SlavikMe Merci beaucoup pour le commentaire! Cependant, votre suggestion donne un résultat différent. Votre suggestion obtient les X premières lignes du fichier totalement trié, alors que nous voulions obtenir les X premières lignes par "clé" (c'est-à-dire si vous avez un CSV avec des noms, alors si vous triez par la colonne 2 "nom de famille" alors vos commandes n'obtiendraient peut-être que 3 lignes avec "Allen" comme nom de famille alors que la nôtre obtiendrait "Allen", "Brittain", "Charles" etc). Merci quand même!
Daniel Iversen le
6
Vous avez tort. J'aurais suggéré d'essayer la commande que j'ai écrite avant de commenter. Notez qu'il existe une commande uniqdans l'ordre des tubes, entre le sortet le head, qui donne une unicité à toutes les lignes triées juste avant l'extraction des premières lignes.
Slavik Meltser