Intereting Posts
Настройка сервера vnc в машинах RHEL Использовать клавиатурно-интерактивную аутентификацию при подключении ssh к другой команде Чтение каталога в сценарии оболочки Найти позицию совпадающего слова в строке в bash (не в позиции символа) Удалить строку между двумя разными разделителями Является ли это поведение хвоста в командах группировки, заданных POSIX? Есть ли стандарт PAM? Использование TMUX при загрузке Linux CentOS Рок-стабильная файловая система для больших файлов (резервное копирование) для Linux Любой способ предоставить отдельный файл vimrc всего за 1 сеанс Создание копий каталогов с помощью find Нужно ли устанавливать mosh-сервер на моем сервере, чтобы использовать Mosh? Возможность сделать перо более заметным на экране в xournal pmount зависает на автозаполнении BASH Как конвертировать Linux-систему с виртуальной машины на физическую машину без потери данных?

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

Я пытаюсь сортировать по нескольким столбцам. Результаты не так ожидаемы.

Вот мои данные (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 

Правильно работает следующее:

 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 

Но следующее не работает, как ожидалось:

 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 

Я пытался сортировать по фамилии, а затем по имени, но вы увидите, что Villamors не в правильном порядке. Я надеялся сортировать по фамилии, а затем, когда фамилии совпали, сортировать по имени.

Кажется, есть что-то о том, как это должно работать, я не понимаю. Я мог бы сделать это по-другому (используя awk), но я хочу понять, как это сделать.

Я использую стандартную оболочку Bash в Mac OS X.

Ключевая спецификация, такая как -k2 означает учет всех полей от 2 до конца строки. Так Villamor 44 заканчивается до Villamor 50 . Поскольку эти два не равны, первое сравнение в sort -k2 -k1 достаточно, чтобы различать эти две строки, а второй ключ сортировки -k1 не вызывается. Если бы у двух Villamors был такой же возраст, -k1 заставил бы их сортировать по имени.

Для сортировки по одному столбцу используйте -k2,2 в качестве ключевой спецификации. Это означает использование полей от # 2 до # 2, т. Е. Только второе поле.

sort -k2 -k3 <people.txt избыточен: он эквивалентен sort -k2 <people.txt . Для сортировки по фамилиям, именам, потом возрастам

 sort -k2,2 -k1,1 <people.txt 

или эквивалентно sort -k2,2 -k1 <people.txt поскольку есть только эти три поля и разделители одинаковы. Фактически, вы получите тот же эффект от sort -k2,2 <people.txt , потому что sort использует всю строку в качестве последнего средства, когда все ключи в подмножестве строк идентичны.

Также обратите внимание, что разделителем полей по умолчанию является переход между непустым и пустым, поэтому ключи будут включать в себя ведущие пробелы (в вашем примере для первой строки первый ключ будет "Emily" , но второй ключ " Bedford" . Добавьте опцию -b чтобы снять эти пробелы:

 sort -b -k2,2 -k1,1 

Это также можно сделать по принципу «ключ», добавив флаг b в конце спецификации запуска ключа:

 sort -k2b,2 -k1,1 <people.txt 

Но что-то, о чем нужно помнить: как только вы добавляете один такой флаг в спецификацию ключа, глобальные флаги (например, -n , -r …) больше не применяются к ним, поэтому лучше избегать смешивания флажков с ключом и глобальные флаги.

С помощью GNU sort вы делаете это так, не уверены в MacOS:

 sort -k2,2 -k1 <people.txt 

Обновление в соответствии с комментарием. Цитата из man sort :

  -k, --key=KEYDEF sort via a key; KEYDEF gives location and type KEYDEF is F[.C][OPTS][,F[.C][OPTS]] for start and stop position, where F is a field number and C a character position in the field; both are origin 1, and the stop position defaults to the line's end.