Jak wykonać niestandardowe sortowanie przy użyciu sortowania unixowego?


11

Używam sortowania unixowego do sortowania pliku rozdzielanego przecinkami z wieloma kolumnami. Do tej pory działało to doskonale do sortowania danych w kolejności numerycznej lub alfabetycznej:

Przykładowy plik przed jakimkolwiek sortowaniem:

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

Sortuj plik: $ sort -t ',' -k 2,2 -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

Posortowany wynik:

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

Oto problem: chcę posortować kolumnę 2 na podstawie sortowania niestandardowego, co oznacza, że ​​najpierw chcę Stany Zjednoczone, potem Kanada, a następnie Bahamy:

Pożądany sort:

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

Czy jest jakiś sposób, aby przekazać sortowanie uniksowe niestandardową kolejność sortowania, którą można zastosować? Coś jak: $ sort -t ',' -k 2,2:'United States, Canada, Bahamas' -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

Dzięki!


3
Dla tych trzech wartości chcesz odwrócić kolejność alfabetyczną. W ogólnym przypadku musisz zmapować nazwy na numer porządkowy sortowania, a następnie wykonać sortowanie przy użyciu numeru porządkowego sortowania. Lub wybierz język skryptowy ... Jedną z możliwości jest joinpolecenie, ale możesz skończyć z wieloma sortowaniami - pliki wejściowe dla joinmuszą być posortowane w jednej kolejności, a następnie będziesz używał sortponownie, aby umieścić dane w inna kolejność (i utrata kolumny kolejności sortowania jako krok po sortowaniu).
Jonathan Leffler

Czy w twoim przykładowym danych wejściowych nie powinno być tzamiast fw ostatnim wierszu?
Lev Levitsky

Lew: tak, dobry haczyk. Mój błąd; zbyt dużo wycinania i wklejania (mój rzeczywisty zestaw danych jest znacznie większy i przypadkowo złapałem niewłaściwe wiersze).

Zaktualizowałem odpowiedź, aby pasowała do twoich danych.
Lev Levitsky

Odpowiedzi:


8

Inna odpowiedź i komentarz ogólnie odpowiadają na pytanie, oto jak może wyglądać implementacja:

$ 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

Wspaniale, dziękuję za twoją pomoc. To działało idealnie!

@jewelia Jeszcze raz poprawiona, sednie była tu naprawdę potrzebna.
Lev Levitsky

1

Nie możesz tego zrobić z sortowaniem . W tym momencie naprawdę powinieneś sięgnąć po awk / perl / your-language-of-choice . Możesz jednak to zrobić. Możesz na przykład użyć sed, aby zmienić „Stany Zjednoczone” na 0, „Kanada” na 1 i „Bahamy” na 2, a następnie wykonać sortowanie liczbowe względem tej kolumny, a następnie odwrócić. Lub zmień „Stany Zjednoczone” na „Stany Zjednoczone, 0” itd., Posortuj według dodatkowej kolumny, a następnie odrzuć ją.


0

Właśnie napisałem pomocnika o imieniu csort, aby ułatwić to. Poprzedza każdą linię wybraną wartością na podstawie podłańcuchów lub dopasowań wyrażeń regularnych w linii:

$ 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Środki notacji „mecz czy drugie pole jest równe STR”.

Następnie możesz opcjonalnie przesłać dane wyjściowe, cut -c3-aby usunąć prefiks.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.