Menyortir banyak kunci dengan sort Unix

140

Saya memiliki file yang berpotensi besar yang perlu diurutkan berdasarkan kunci 1-n. Beberapa dari kunci ini mungkin berupa angka dan beberapa mungkin tidak. Ini adalah file kolom lebar tetap jadi tidak ada pembatas.

Apakah ada cara yang baik untuk melakukan ini dengan semacam Unix? Dengan satu kunci, semudah menggunakan '-n'. Saya telah membaca halaman manual dan mencari Google sebentar, tetapi tidak menemukan contoh yang baik. Bagaimana saya bisa mencapai ini?

Catatan: Saya telah mengesampingkan Perl karena potensi ukuran file. Ini akan menjadi pilihan terakhir.

Chris Kloberdanz
sumber
Satu atau dua baris data contoh akan sangat membantu untuk membuat baris perintah contoh. Selain itu, apakah kunci "1-n" berarti Anda perlu mengurutkan berdasarkan sejumlah variabel kunci? Melakukan itu tanpa scripting akan menyenangkan ...
Ken Gentle
Saya memiliki pembungkus PHP di sekitar perintah sortir untuk mengaktifkan fitur 1-n.
Chris Kloberdanz

Jawaban:

70

Gunakan -kopsi (atau --key=POS1[,POS2]). Itu dapat muncul beberapa kali dan setiap kunci dapat memiliki opsi global (seperti nuntuk urutan numerik)

Ken Gentle
sumber
7
Dari halaman manual sortir: "POS adalah F [.C] [OPTS], di mana F adalah nomor lapangan dan C adalah posisi karakter di lapangan; keduanya adalah asal 1." Lihat halaman manual untuk dokumentasi lengkap.
Adam Rosenfield
51
Lihat juga jawaban andras jika tidak ingin menjadi gila.
ron
1
Kedua komentar di atas akurat dan aditif. Terima kasih, Tuan-tuan.
Ken Gentle
320

Berhati-hatilah:

Jika Anda ingin mengurutkan file berdasarkan bidang 3, dan yang kedua menurut bidang 2 Anda menginginkan ini:

sort -k 3,3 -k 2,2 < inputfile

Bukan ini: sort -k 3 -k 2 < inputfile yang mengurutkan file berdasarkan string dari awal bidang 3 hingga akhir baris (yang berpotensi unik).

-k, --key=POS1[,POS2]     start a key at POS1 (origin 1), end it at POS2
                          (default end of line)
andras
sumber
9
Mengubah hidup. Terima kasih.
davidtbernal
2
Ups! Sekarang saya harus memperbaiki skrip karena sebelumnya saya hanya melihat jawaban pertama di atas ... untungnya saya belum bergantung pada keluaran skrip ....
Wildcard
3
@Arun POS dijelaskan di akhir halaman manual. Anda cukup menambahkan opsi pemesanan ke nomor bidang seperti ini:sort -k 3,3nr -k 2,2
andras
1
Aargh. Apa antarmuka yang berlawanan dengan intuisi: -k2harus -k2,2dan tanda koma -k2,harus 'akhir baris default magis atau apa pun'.
android.weasel
1
Astaga. Penulis halaman manual memenangkan kontes untuk cara yang paling tidak membantu untuk mendokumentasikannya. Saya telah membaca halaman manual Unix selama 28 tahun. Tidak ada tempat menyebutkan bidang -k dapat diulangi.
BaseZen
95

Opsi -k adalah yang Anda inginkan.

-k 1.4,1.5n -k 1.14,1.15n

Akan menggunakan posisi karakter 4-5 di bidang pertama (itu semua satu bidang untuk lebar tetap) dan mengurutkan secara numerik sebagai kunci pertama.

Kunci kedua akan menjadi karakter 14-15 di bidang pertama juga.

(edit)

Contoh (yang saya miliki hanyalah DOS / cygwin berguna):

dir | \cygwin\bin\sort.exe -k 1.4,1.5n -k 1.40,1.60r

untuk data:

12/10/2008  01:10 PM         1,564,990 outfile.txt

Mengurutkan daftar direktori berdasarkan nomor bulan (pos 4-5) secara numerik, kemudian menurut nama file (pos 40-60) secara terbalik. Karena tidak ada tab, semua kolom 1 harus diurutkan.

Clinton Pierce
sumber
Ini hanya satu bidang jika tidak ada bagian yang kosong dalam data masukan. Meskipun demikian, teladan Anda berguna.
Jonathan Leffler
Koreksi: jika tidak ada / tab / pada input data. Dalam output perintah 'dir' DOS, tidak ada tab.
Clinton Pierce
1
Contoh tentang bagaimana menggunakan opsi (numerik, terbalik) sangat membantu, karena hampir tidak mungkin untuk mengetahui bagaimana menggunakan hanya dari halaman manual dan jawaban lain tidak menyebutkannya. Saya berharap saya bisa +2 untuk ini. ;)
msb
23

Berikut adalah satu untuk mengurutkan berbagai kolom dalam file csv berdasarkan urutan numerik dan kamus, kolom 5 dan setelahnya sebagai urutan kamus

~/test>sort -t, -k1,1n -k2,2n -k3,3d -k4,4n -k5d  sort.csv
1,10,b,22,Ga
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C

~/test>cat sort.csv
2,3,a,9,C
2,2,b,20,F
2,2,c,19,Gb,hj
2,2,c,19,Gb,hi
2,2,c,19,Ga
2,2,b,22,Ga
1,10,b,22,Ga

Perhatikan -k1,1n berarti numerik mulai dari kolom 1 dan berakhir di kolom 1. Jika saya lakukan di bawah ini, itu akan menggabungkan kolom 1 dan 2 membuat 1,10 diurutkan sebagai 110

~/test>sort -t, -k1,2n -k3,3 -k4,4n -k5d  sort.csv
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C
1,10,b,22,Ga
edW
sumber
2
Ini adalah jawaban terbaik karena ini menunjukkan bagaimana menggunakan sakelar yang berbeda untuk kolom yang berbeda
xaxa
12

Saya percaya dalam kasus Anda sesuatu seperti

sort -t@ -k1.1,1.4 -k1.5,1.7 ... <inputfile

akan bekerja lebih baik. @ adalah pemisah bidang, pastikan karakter tersebut tidak muncul di mana pun. maka masukan Anda dianggap terdiri dari satu kolom.

Edit: ternyata clintp sudah memberikan jawaban serupa, maaf. Seperti yang dia tunjukkan, bendera 'n' dan 'r' dapat ditambahkan ke setiap opsi -k .....

Dong Hoon
sumber
Meskipun pemisah default yang sesuai dengan docs gnu.org/software/coreutils/manual/html_node/… adalah spasi, terkadang jumlah kolom tidak seperti yang Anda harapkan. Mungkin seperti yang dikatakan orang lain di sini karena pengaturan lokal LC_CTYPE. Jika ragu, hitung dari awal baris!
Brad Dre
5

Perhatikan bahwa mungkin juga diinginkan untuk menstabilkan pengurutan dengan -ssakelar, sehingga garis dengan peringkat yang sama mempertahankan urutan relatif aslinya di keluaran juga.

ron
sumber
2

Saya hanya ingin menambahkan beberapa tip, ketika Anda menggunakan sort, berhati-hatilah dengan lokal Anda yang mempengaruhi urutan perbandingan kunci. Saya biasanya secara eksplisit menggunakan LC_ALL = C untuk membuat lokal apa yang saya inginkan.

jianpx
sumber
LC_ALL = C juga dapat menghasilkan kecepatan yang cukup tinggi!
tikar kelcey