J'essaie de trier sur plusieurs colonnes. Les résultats ne sont pas ceux attendus.
Voici mes données (people.txt):
Simon Strange 62
Pete Brown 37
Mark Brown 46
Stefan Heinz 52
Tony Bedford 50
John Strange 51
Fred Bloggs 22
James Bedford 21
Emily Bedford 18
Ana Villamor 44
Alice Villamor 50
Francis Chepstow 56
Ce qui suit fonctionne correctement :
bash-3.2$ sort -k2 -k3 <people.txt
Emily Bedford 18
James Bedford 21
Tony Bedford 50
Fred Bloggs 22
Pete Brown 37
Mark Brown 46
Francis Chepstow 56
Stefan Heinz 52
John Strange 51
Simon Strange 62
Ana Villamor 44
Alice Villamor 50
Mais, ce qui suit ne fonctionne pas comme prévu :
bash-3.2$ sort -k2 -k1 <people.txt
Emily Bedford 18
James Bedford 21
Tony Bedford 50
Fred Bloggs 22
Pete Brown 37
Mark Brown 46
Francis Chepstow 56
Stefan Heinz 52
John Strange 51
Simon Strange 62
Ana Villamor 44
Alice Villamor 50
J'essayais de trier par nom de famille puis par prénom, mais vous verrez que les Villamor ne sont pas dans le bon ordre. J'espérais trier par nom de famille, puis lorsque les noms de famille correspondaient, trier par prénom.
Il semble qu'il y ait quelque chose sur la façon dont cela devrait fonctionner que je ne comprends pas. Je pourrais le faire d'une autre manière bien sûr (en utilisant awk), mais je veux comprendre le tri.
J'utilise le shell Bash standard sur Mac OS X.
Réponse acceptée :
Une spécification de clé comme -k2
signifie prendre en compte tous les champs de 2 à la fin de la ligne. Alors Villamor 44
se termine avant Villamor 50
. Puisque ces deux ne sont pas égaux, la première comparaison dans sort -k2 -k1
suffit à discriminer ces deux lignes, et la deuxième clé de tri -k1
n'est pas invoqué. Si les deux Villamor avaient eu le même âge, -k1
les aurait fait trier par prénom.
Pour trier par une seule colonne, utilisez -k2,2
comme spécification clé. Cela signifie utiliser les champs de #2 à #2, c'est-à-dire uniquement le deuxième champ.
sort -k2 -k3 <people.txt
est redondant :il est équivalent à sort -k2 <people.txt
. Pour trier par noms, puis prénoms, puis âge, exécutez la commande suivante :
sort -k2,2 -k1,1 <people.txt
ou de manière équivalente sort -k2,2 -k1 <people.txt
puisqu'il n'y a que ces trois champs et que les séparateurs sont les mêmes. En fait, vous obtiendrez le même effet avec sort -k2,2 <people.txt
, car sort
utilise la ligne entière en dernier recours lorsque toutes les clés d'un sous-ensemble de lignes sont identiques.
Notez également que le séparateur de champs par défaut est la transition entre un non-blanc et un blanc, donc les clés incluront les blancs de tête (dans votre exemple, pour la première ligne, la première clé sera "Emily"
, mais la seconde clé " Bedford"
. Ajoutez le -b
option pour supprimer ces blancs :
sort -b -k2,2 -k1,1
Cela peut également être fait clé par clé en ajoutant le b
drapeau à la fin de la spécification de démarrage de clé :
sort -k2b,2 -k1,1 <people.txt
Mais quelque chose à garder à l'esprit :dès que vous ajoutez un tel indicateur à la spécification de la clé, les indicateurs globaux (comme -n
, -r
…) ne s'appliquent plus à eux donc mieux vaut éviter de mélanger les drapeaux par clé et les drapeaux globaux.