Сортировать данные в порядке убывания первого столбца, для одинаковых значений использовать второй столбец в порядке возрастания

22

Позвольте мне уточнить:

Предположим, у меня есть несколько ключевых слов с частотой их использования:

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

Я хочу отсортировать эти данные по частоте в порядке убывания, и, если есть какие-то равные значения, следует использовать второй столбец в порядке возрастания.

sort -n -r foo.txt

Имеет ли первая часть, а затем второй столбец также reversed:

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

Как я могу добиться следующих результатов?

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

Я думаю, что должен использовать -kаргумент, но я не могу понять, как!

Я хочу знать, как это можно сделать, используя только sortкоманду bash. Однако, если это невозможно сделать только с помощью sortдругих команд, они должны быть совместимы с оболочкой Bourne.

Pouya
источник
[Отчасти OT]: хотя это и эквивалентно для этих конкретных данных, использование -gопции GNU-sort (общие числовые) вместо -nчисловых сравнений безопаснее: она работает корректно как для чисел с плавающей запятой, так и для целых чисел.
Ариэльф

Ответы:

32

Укажите ключи сортировки отдельно с критериями:

sort -k1,1nr -k2,2 inputfile

Это указывает на то, что первый ключ сортируется по номерам в обратном порядке, а второй - по порядку сортировки по умолчанию .

Цитирование из сортировки POSIX :

-k keydef

Keydef аргумент является ограниченным ключом сортировки определения поля. Формат этого определения:

field_start [ тип ] [ , field_end [ тип ]]

где field_start и field_end определяют ключевое поле, ограниченное частью строки (см. раздел РАСШИРЕННОЕ ОПИСАНИЕ), а type является модификатором из списка символов 'b', 'd', 'f', 'i', ' n ',' r '. Модификатор 'b' должен вести себя как -bопция, но должен применяться только к field_start или field_end, к которому он присоединен. Другие модификаторы должны вести себя как соответствующие опции, но должны применяться только к ключевому полю, к которому они присоединены; они должны иметь этот эффект, если они указаны с помощью field_start , field_end или обоих., ни один из вариантов не должен применяться ни к одному. Реализации должны поддерживать по крайней мере девять вхождений -kопции, которые должны быть значительными в порядке командной строки. Если -kопция не указана, должен использоваться ключ сортировки по умолчанию для всей строки.

Когда имеется несколько полей ключей, более поздние ключи сравниваются только после того, как все предыдущие ключи сравниваются равными. За исключение случаев, когда -uуказан параметр, строки , которые в противном случае сравнения равно должны быть заказаны как если ни один из вариантов -d, -f, -i, -n, или -kприсутствовали (но все -r еще в силе, если он был указан) и со всеми байтами в линиях , значимых для сравнение. Порядок, в котором записываются строки, которые по-прежнему сравниваются, не указан.

Это даст:

42 Life
17 Stackoverflow
12 Hi
9  LaTeX
9  Superuser
9  Ubuntu
7  C++
7  Hash
devnull
источник
Спасибо. Сделал трюк. Нужно ждать 10 минут, чтобы принять!
Pouya
@StephaneChazelas Спасибо за указание на это; обновил ссылку.
devnull