GNU/Linux >> Tutoriels Linux >  >> Linux

Essayer de trier sur deux champs, deuxième puis premier ?

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.

Connexe :Comment rechercher du texte dans un fichier et afficher le paragraphe contenant le texte ?

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.


Linux
  1. Comment faire un Ls puis trier les résultats par date de création ?

  2. Passer à une deuxième session X tue le premier ?

  3. Trier par valeur hexadécimale ?

  4. Trier la sortie par colonne ?

  5. Fichier de tri du shell Linux selon la deuxième colonne ?

Comment puis-je obtenir des mots entre les deux premières instances de texte/motif ?

Comment faire en sorte que ls soit trié par extension de fichier puis par nom?

Tri GNU sensible à la casse

Comment puis-je faire en sorte que ls affiche d'abord les fichiers de points?

Comment échanger les premier et deuxième flux audio dans un MKV dans un système basé sur Linux ?

Comment trier les résultats de la commande ls par date de modification (répertoires en premier) ?