Bagaimana cara penyortiran khusus menggunakan penyortiran unix?

11

Saya menggunakan unix sort untuk mengurutkan file yang dibatasi koma dengan beberapa kolom. Sejauh ini, ini telah bekerja dengan sempurna untuk mengurutkan data baik secara numerik atau dalam urutan abjad:

Contoh file sebelum disortir:

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

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

Hasil yang diurutkan:

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

Inilah masalahnya: Saya ingin mengurutkan kolom 2 berdasarkan jenis kustom, artinya saya ingin Amerika Serikat dulu, lalu Kanada, lalu Bahama:

Sortir yang diinginkan:

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

Apakah ada beberapa cara untuk lulus unix sort urutan pesanan khusus yang kemudian dapat diterapkan? Sesuatu seperti: $ sort -t ',' -k 2,2:'United States, Canada, Bahamas' -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

Terima kasih!


sumber
3
Untuk ketiga nilai ini, Anda ingin membalik urutan alfabet. Untuk kasus umum, Anda harus memetakan nama ke nomor urut urutan, dan kemudian melakukan pengurutan menggunakan nomor urut urutan. Atau joingunakan bahasa scripting ... Satu kemungkinan adalah perintah, tetapi Anda bisa berakhir dengan banyak penyortiran - file input untuk joinharus diurutkan dalam satu urutan, dan kemudian Anda akan menggunakan sortlagi untuk memasukkan data ke dalam urutan berbeda (dan kehilangan kolom urutan sortir sebagai langkah pasca-sortir).
Jonathan Leffler
Dalam masukan contoh Anda, seharusnya tidak ada tbukannya fdi baris terakhir?
Lev Levitsky
Lev: ya, tangkapan yang bagus. Salahku; terlalu banyak memotong dan menempel (kumpulan data saya yang sebenarnya jauh lebih besar dan saya tidak sengaja mengambil baris yang salah).
Saya memperbarui jawaban untuk mencocokkan data Anda.
Lev Levitsky

Jawaban:

8

Jawaban dan komentar lainnya menjawab pertanyaan secara umum, begini tampilannya bisa seperti:

$ 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
Lev Levitsky
sumber
Luar biasa, terima kasih atas bantuan Anda. Ini bekerja dengan sempurna!
@jewelia Ditingkatkan sekali lagi, sedtidak benar-benar diperlukan di sini.
Lev Levitsky
1

Anda tidak dapat melakukan itu dengan sortir . Pada titik ini, Anda benar-benar harus meraih awk / perl / bahasa-pilihan Anda . Anda bisa memperdayainya. Misalnya, Anda dapat menggunakan sed untuk mengubah "Amerika Serikat" menjadi 0, "Kanada" menjadi 1 dan "Bahama" menjadi 2, lalu melakukan pengurutan angka terhadap kolom itu, lalu mengembalikannya. Atau ubah "Amerika Serikat" menjadi "Amerika Serikat, 0" dll., Urutkan berdasarkan kolom tambahan lalu buang.

itu otaknya
sumber
0

Saya baru saja menulis pembantu yang disebut csort untuk memudahkan melakukan ini. Ini mengawali setiap baris dengan nilai yang Anda pilih berdasarkan kecocokan substring atau persamaan reguler dalam baris:

$ 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

The 2=STRnotasi berarti "pertandingan jika kolom kedua sama STR".

Anda kemudian dapat secara opsional menyalurkan output cut -c3-untuk menghapus awalan.

Adam Spires
sumber