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.


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)


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)

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.


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

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 .....


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.


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.


LC_ALL = C juga dapat menghasilkan kecepatan yang cukup tinggi!
tikar kelcey
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.