Як зробити власне сортування за допомогою сортування Unix?


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 -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 / вашої мови на вибір . Ти можеш це погладити. Наприклад, ви можете використовувати 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.