Как сделать пользовательскую сортировку с использованием unix sort?


11

Я использую Unix для сортировки файла с разделителями-запятыми с несколькими столбцами. До сих пор это отлично работало для сортировки данных по номерам или по алфавиту:

Файл примера перед любой сортировкой:

C,United States,WA,Tacoma,f,1
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2
A,United States,NY,New York,f,1

Сортировать файл: $ sort -t ',' -k 2,2 -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

Сортированный результат:

A,Bahamas,Bahamas,Nassau,f,2
A,Canada,QC,Montreal,f,2
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1

Вот проблема: я хочу отсортировать столбец 2 на основе пользовательской сортировки, что означает, что я хочу сначала Соединенные Штаты, затем Канаду, а затем Багамские острова:

Желаемый вид:

A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2

Есть ли способ передать unix sort пользовательский порядок сортировки, который затем можно применить? Что-то вроде: $ sort -t ',' -k 2,2:'United States, Canada, Bahamas' -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

Спасибо!


3
Для этих трех значений требуется обратный алфавитный порядок. В общем случае вам необходимо сопоставить имена с порядковым номером сортировки, а затем выполнить сортировку с использованием порядкового номера сортировки. Или перейдите на язык сценариев ... Одной из возможностей является joinкоманда, но вы можете получить много сортировок: входные файлы joinдолжны быть отсортированы в одном порядке, а затем вы sortснова будете использовать их для помещения данных в другой порядок (и потеря столбца порядка сортировки как шаг после сортировки).
Джонатан Леффлер

В вашем примере ввода, не должно быть tвместо fпоследней строки?
Лев Левицкий

Лев: да, хороший улов. Виноват; слишком много вырезок и вставок (мой фактический набор данных намного больше, и я случайно выхватил неправильные строки).

Я обновил ответ в соответствии с вашими данными.
Лев Левицкий

Ответы:


8

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

$ cat order
Bahamas,3
Canada,2
United States,1

$ cat data
C,United States,WA,Tacoma,f,1
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2
A,United States,NY,New York,f,1

$ sort -t, -k2 data | join -t, -11 -22 order - | sort -t, -k2n -k4,5 -k6r -k7nr | cut -d, -f 3,1,4-7
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2

Отлично, спасибо за вашу помощь. Это сработало отлично!

@jewelia Улучшено еще раз, здесь sedне было необходимости.
Лев Левицкий

1

Вы не можете сделать это с помощью сортировки . На этом этапе вы действительно должны использовать awk / perl / your-language-of-choice . Вы можете обмануть это, хотя. Вы можете, например, использовать sed, чтобы изменить «Соединенные Штаты» на 0, «Канада» на 1 и «Багамские острова» на 2, затем выполнить числовую сортировку по этому столбцу, а затем вернуть его обратно. Или измените «Соединенные Штаты» на «Соединенные Штаты, 0» и т. Д., Сортируйте по дополнительному столбцу и затем отбрасывайте его.


0

Я только что написал помощник csort, чтобы сделать это легко. Он добавляет к каждой строке значение по вашему выбору на основе совпадений подстроки или регулярного выражения в строке:

$ csort -t, '2=United States' X 2=Canada Y 2=Bahamas Z < tmp.csv | \
sort -t, -k1,1 -k3,3 -k4,4 -k5,5 -k6,6r -k7,7nr
X,A,United States,MA,Boston,f,0
X,B,United States,NY,New York,f,5
X,A,United States,NY,New York,f,1
X,C,United States,WA,Tacoma,f,1
Y,A,Canada,QC,Montreal,f,2
Z,A,Bahamas,Bahamas,Nassau,f,2

2=STRЗапись означает «совпадение , если второе поле равно STR».

Затем вы можете при желании передать вывод, cut -c3-чтобы удалить префикс.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.