Сортировка CSV-файла по приоритету столбца с помощью команды «sort»

95

У меня есть CSV-файл, и я хотел бы отсортировать его по приоритету столбца, например «по порядку». Например:

3;1;2
1;3;2
1;2;3
2;3;1
2;1;3
3;2;1

Если бы эта ситуация была результатом «выбора», «упорядочить по» было бы следующим образом: упорядочить по столбцу 2, столбцу 1, столбцу 3 - результат будет:

2;1;3
3;1;2
1;2;3
3;2;1
1;3;2
2;3;1

Я хотел бы знать, как получить тот же результат, используя команду «sort» в Unix.

Рафаэль Ораджио
источник
4
Кстати, это файл ssv (значения, разделенные точкой с запятой): P
Джон Струд

Ответы:

157
sort --field-separator=';' --key=2,1,3
Чарли Мартин
источник
9
Если значения являются числовыми, то вы, вероятно, захотите рассмотреть возможность использования -nопции, которая будет «сравнивать по числовому значению строки», или -gопции, которая будет «сравнивать по общему числовому значению». При строковом сравнении числовых значений числа будут упорядочены как 1,10,2,20. По крайней мере, это варианты, доступные в моей версии сортировки на CentOS. Вы должны проверить на странице руководства, какие правильные параметры есть в вашей версии sort.
Adam Porad
5
Я получаюsort: stray character in field spec: invalid field specification ‘2,1,3’
Мартин Тома
3
Однако sort --field-separator=',' -r -k3 -k1 -k2 source.csv > target.csvу меня сработало.
Мартин Тома,
6
@MartinThoma, это было давно, но я столкнулся с вашей проблемой и нашел ее sort --field-separator=';' --key={2,1,3}. Это работало GNU coreutils 8.4с апреля 2016 года
мрболичи
3
@mrbolichi в нотации --key={2,1,3}используется расширение bash в фигурных скобках
квантур
29

Предположим, у вас есть еще одна строка 3;10;3в вашем unsorted.csvфайле. Тогда я думаю, вы ожидаете численно отсортированного результата:

2;1;3
3;1;2
1;2;3
3;2;1
1;3;2
2;3;1
3;10;3

а не отсортированный по алфавиту:

2;1;3
3;1;2
3;10;3
1;2;3
3;2;1
1;3;2
2;3;1

Чтобы получить это, вы должны использовать -n:

sort --field-separator=';' -n -k 2,2 -k 1,1 -k 3,3 unsorted.csv

Стоит упомянуть, что 2,2нужно использовать. Если 2используется только , то sortпереносит строку от начала поля 2 до конца. 2,2гарантирует, что используется только поле 2.

Мартин Тома
источник
8
Указатель на разницу между -k 2 и -k 2,2 существенен! Я упустил это из виду при первом чтении страницы руководства. Спасибо.
usonianhorizon 08
Я добавил несколько дополнительных строк, 3;10;3, 3:10:5, 3:10;2, 3;10;3в том порядке , в исходном файле, а при использовании только -k 2,2 оказывается для сортировки по колонке 2 и 3. Страница человек говорит "The -k option may be specified multiple times, in which case subsequent keys are compared when earlier keys compare equal.". В моем случае предыдущий ключ (значение = 10) сравнивался с равным, однако я не указывал -kнесколько раз. Я не уверен, что это надежное поведение или связано с моей системой (Mac). В конечном итоге это не имеет значения, если первичная сортировка верна.
Давос
О, я вижу, есть также -sстабильная сортировка, которая игнорирует одинаковые ключи, что, по-видимому, быстрее, по мнению человека.
Давос
24

Приведенный выше ответ Чарли не сработал для меня в Cygwin (версия сортировки 2.0, GNU textutils), следующее:

sort -t"," -k2 -k1 -k1
Сэмюэл Керриен
источник
3
Cygwin имеет более старую версию sort. Как всегда, страница руководства - ваш друг.
Чарли Мартин
2
Я согласен с @CharlieMartin, вам следует проверить страницу руководства в своей системе. На CentOS я использовалsort --field-separator=';' -k2 -k1 -k3 test.csv
Адам Порад,
-6

..и если кто-то следовал решению 'sort', но теперь хочет получить больше одной уникальной записи в строке (т.е. максимальное количество уникальных записей X), как только вы отсортировали файл с помощью 'sort', вы можете использовать небольшое приложение, которое я создал здесь:

https://github.com/danieliversen/MiscStuff/blob/master/scripts/findTopUniques.java

Даниэль Иверсен
источник
2
Повезло тебе! Но в вашем случае вы могли бы просто использовать cat unsorted-file | sort | uniq | head -X- when X- количество первых строк, которые вы хотите вывести.
Славик Мельцер
@SlavikMe Большое спасибо за комментарий! Однако ваше предложение дает другой результат. Ваше предложение получает первые X строк в полностью отсортированном файле, в то время как мы хотели получить первые X строк на «ключ» (т.е. если у вас есть CSV с именами, то если вы отсортируете по столбцу 2 «фамилия» ваши команды, возможно, получат только 3 строки с фамилией «Аллен», тогда как наши команды получат «Аллен», «Бриттен», «Чарльз» и т. д.). Спасибо хоть!
Daniel Iversen
6
ты неправ. Я бы предложил попробовать команду, которую я написал, прежде чем комментировать. Обратите внимание, что есть команда uniqв порядке конвейера между символами « sortи» head, которая дает уникальность всем отсортированным строкам непосредственно перед извлечением верхних строк.
Славик Мельцер