Trier les données dans l'ordre décroissant de la première colonne, pour des valeurs égales, utiliser la deuxième colonne dans l'ordre croissant

22

Permettez-moi de clarifier:

Supposons que j'ai quelques mots clés avec la fréquence de leur utilisation:

12 Hi
7  Hash
7  C++  
9  Superuser
17 Stackoverflow
9  LaTeX  
42 Life
9  Ubuntu

Ce que je veux, c'est trier ces données en fonction de la fréquence en ordre décroissant et s'il y a des valeurs égales, il devrait utiliser la deuxième colonne en ordre croissant.

sort -n -r foo.txt

Est-ce que la première partie mais ensuite la deuxième colonne sont également reversed:

42 Life
17 Stackoverflow
12 Hi
9  Ubuntu
9  Superuser
9  LaTeX  
7  Hash
7  C++

Comment puis-je obtenir les résultats suivants?

42 Life
17 Stackoverflow
12 Hi
9  LaTeX  
9  Superuser
9  Ubuntu
7  C++ 
7  Hash

Je pense que je dois utiliser l' -kargument mais je ne sais pas comment!

Je veux savoir comment cela peut être fait en utilisant uniquement la sortcommande de bash. Cependant, s'il n'est pas possible d'y parvenir uniquement par sort, d'autres commandes devraient être compatibles avec le shell Bourne.

Pouya
la source
[Un peu OT]: bien qu'équivalent pour ces données particulières, l'utilisation de l' -goption de tri GNU (numérique général) au lieu de -npour les comparaisons numériques est plus sûre: elle fonctionne correctement pour les virgules flottantes et les entiers.
arielf

Réponses:

32

Spécifiez les clés de tri séparément avec les critères:

sort -k1,1nr -k2,2 inputfile

Cela spécifie que la première clé est triée numériquement dans l'ordre inverse tandis que la seconde est triée selon l' ordre de tri par défaut .

Citant du tri POSIX :

-k keydef

L' argument keydef est une définition de champ de clé de tri restreint. Le format de cette définition est:

field_start [ type ] [ , field_end [ type ]]

field_start et field_end définissent un champ clé limité à une partie de la ligne (voir la section DESCRIPTION ÉTENDUE) et le type est un modificateur de la liste des caractères «b», «d», «f», «i», « n ',' r '. Le modificateur 'b' se comportera comme l' -boption, mais ne s'appliquera qu'au field_start ou field_end auquel il est attaché. Les autres modificateurs se comportent comme les options correspondantes, mais ne s'appliquent qu'au champ clé auquel ils sont attachés; ils doivent avoir cet effet s'ils sont spécifiés avec field_start , field_end ou les deux., aucune option ne s'applique à l'un ou l'autre. Les implémentations doivent prendre en charge au moins neuf occurrences de l' -koption, qui doivent être significatives dans l'ordre de la ligne de commande. Si aucune -koption n'est spécifiée, une clé de tri par défaut de la ligne entière doit être utilisée.

Lorsqu'il y a plusieurs champs de clé, les clés ultérieures ne seront comparées qu'après que toutes les clés antérieures auront été égales. À l' exception lorsque l' -uoption est spécifiée, les lignes qui , autrement , être égaux doivent être commandés comme si aucune des options -d, -f, -i, -nou -kétaient présents (mais -r toujours en vigueur, si elle a été spécifiée) et avec tous les octets dans les lignes significatives au Comparaison. L'ordre dans lequel les lignes qui se comparent toujours égales sont écrites n'est pas spécifié.

Cela produirait:

42 Life
17 Stackoverflow
12 Hi
9  LaTeX
9  Superuser
9  Ubuntu
7  C++
7  Hash
devnull
la source
Merci. A fait l'affaire. Faut attendre 10 minutes pour accepter!
Pouya
@StephaneChazelas Merci de l'avoir signalé; a mis à jour la référence.
devnull