Sortir berdasarkan kolom ketiga

132

Saya menghadapi file 4 kolom yang sangat besar. Saya ingin menampilkan file yang diurutkan di stdout berdasarkan kolom ke-3:

cat myFile | sort -u -k3

Apakah itu cukup untuk melakukan triknya?

pengguna1058398
sumber
4
Perhatikan bahwa Anda dapat menulis ini sebagai sort -u -k3 < myFile.
gerrit
6
Sebagai sort -u -k3 myFile, bahkan
Sebastian Graf

Jawaban:

168
sort -k 3,3 myFile

akan menampilkan file diurutkan oleh 3 rd kolom dengan asumsi kolom dipisahkan oleh urutan kosong (ASCII SPC dan karakter TAB di POSIX / C lokal), menurut urutan ditentukan oleh lokal saat ini.

Perhatikan bahwa blanko terkemuka disertakan dalam kolom (pemisah default adalah transisi dari non-kosong ke kosong), yang dapat membuat perbedaan dalam lokal di mana spasi tidak diabaikan untuk tujuan perbandingan, gunakan -bopsi untuk mengabaikan blanko terkemuka.

Perhatikan bahwa itu sepenuhnya independen dari shell (semua shell akan menguraikan baris perintah yang sama, shell umumnya tidak memiliki sortperintah bawaan).

-k 3adalah untuk mengurutkan bagian dari baris yang dimulai dengan 3 rd kolom (termasuk kekosongan terkemuka). Di lokal C, karena karakter spasi dan tab peringkat sebelum semua karakter yang dapat dicetak, yang umumnya akan memberi Anda hasil yang sama seperti -k 3,3(kecuali untuk baris yang memiliki bidang ketiga yang identik),

-uadalah untuk mempertahankan hanya satu baris jika ada beberapa yang menyortir secara identik (di situlah kunci sortir sama (itu tidak harus sama dengan menjadi sama )).

catadalah perintah untuk menipu kucing . Anda tidak membutuhkannya di sini.

Jika kolom dipisahkan oleh sesuatu yang lain, Anda perlu -topsi untuk menentukan pemisah.

File contoh yang diberikan a

$ cat a
a c c c
a b ca d
a b  c e
a b c d

Dengan -u -k 3:

$ echo $LANG
en_GB.UTF-8

$ sort -u -k 3 a
a b ca d
a c c c
a b c d
a b  c e

Baris 2 dan 3 memiliki kolom ketiga yang sama, tetapi di sini tombol sortirnya adalah dari kolom ketiga hingga akhir baris, jadi -upertahankan keduanya. ␠ca␠dmacam sebelumnya ␠c␠ckarena spasi diabaikan pada pass pertama di lokal saya, cadsemacam sebelumnya cc.

$ sort -u -k 3,3 a
a b c d
a b  c e
a b ca d

Di atas hanya satu yang disimpan untuk yang berada di kolom ke-3 ␠c. Perhatikan bagaimana satu dengan ␠␠c(2 spasi utama) dipertahankan.

$ sort -k 3 a
a b ca d
a c c c
a b c d
a b  c e
$ sort -k 3,3 a
a b c d
a c c c
a b  c e
a b ca d

Lihat bagaimana urutan a b c ddan a c c cdibalik. Dalam kasus pertama, karena ␠c␠cmengurutkan sebelumnya ␠c␠d, dalam kasus kedua karena kunci pengurutan adalah sama ( ␠c), perbandingan pilihan terakhir yang membandingkan garis dalam menempatkan penuh a b c dsebelumnya a c c c.

$ sort -b -k 3,3 a
a b c d
a b  c e
a c c c
a b ca d

Setelah kami mengabaikan bagian yang kosong, kunci pengurutan untuk 3 baris pertama adalah sama ( c), jadi mereka diurutkan berdasarkan perbandingan pilihan terakhir.

$ LC_ALL=C sort -k 3 a
a b  c e
a c c c
a b c d
a b ca d
$ LC_ALL=C sort -k 3,3 a
a b  c e
a b c d
a c c c
a b ca d

Di lokal C, ␠␠cmengurutkan sebelumnya ␠ckarena hanya ada satu lulus di sana karakter (kemudian byte tunggal) mengurutkan berdasarkan nilai titik kode mereka (di mana ruang memiliki titik kode lebih rendah dari c).

Stéphane Chazelas
sumber
kolom blank-terpisah yang mungkin menyertakan karakter lain selain spasi dan tab tergantung pada lokal.
jfs
1
Bagus, +1. Bisakah Anda menjelaskan apa 3,3fungsinya? Kenapa tidak adil 3?
terdon
@terdon, lihat deskripsi yang diperluas dengan contoh.
Stéphane Chazelas
@ JSFSebastian, Anda benar, jawab diperbarui.
Stéphane Chazelas
Ah, untuk membuatnya hanya mengurutkan pada tanggal 3, bukan sisa baris, terima kasih.
terdon
4

Jika Anda memahami "kolom" seperti dalam file teks (karakter ke-4) maka ya, solusi Anda harusnya berfungsi (atau bahkan sort -u -k3 myFilememungkinkan sortmelakukan beberapa sihir penghemat memori dengan akses acak). Jika Anda memahami "kolom" seperti dalam basis data - seluruh entitas data yang diikuti oleh pemisah, dan lebar kolom variabel, Anda akan memerlukan sesuatu yang lebih menarik, mis. Ini mengurutkan ls-l berdasarkan ukuran

      ls -l |awk '{print $5 " " $0;}'| sort -n | cut -d " " -f 2-

(yang setara dengan sepele ls -lStetapi melayani contoh dengan baik.)

SF.
sumber
5
Tidak, secara default semacam kolom kosong dipisahkan, mereka tidak kolom karakter, untuk menyortir pada kolom 3 karakter, sintaks akan: sort -k 1.3,1.3. ls -l | sort -k5,5nuntuk mengurutkan pada ukuran.
Stéphane Chazelas
The awksolusi adalah persis apa yang saya needed-- mudah dimodifikasi agar sesuai dengan kebutuhan penyortiran kompleks
jchook
2
sort -g -k column_number 

adalah perintah yang tepat untuk mengurutkan daftar yang memiliki karakter numerik menggunakan kolom tertentu

Jayant Kumar Jain
sumber
1
Menggunakan -k sudah dibahas dengan cukup baik sehingga akan sangat membantu jika Anda menjelaskan bagaimana perintah ini berbeda atau lebih baik. Mungkin Anda juga bisa memasukkan nomor kolom aktual untuk menjawab pertanyaan aktual OP.
Jeff Schaller
Ini membuat saya menggunakan halaman manual: p "-g, --general-numeric-sort, bandingkan dengan nilai numerik umum" yang merupakan apa yang saya butuhkan dalam kasus saya.
bergabung dengan
1

Anda dapat menggunakan perpustakaan Velk awk :

#!/usr/local/bin/velour -f
{
  q[NR] = $3
  z[NR] = $0
}
END {
  a_sort_by(q, z)
  io_puts(q)
}
Steven Penny
sumber
0
$ sort -k 1.3,1.3 myfile

Akan mengurutkan file myfile Anda pada kolom ketiga jika file Anda tidak memiliki pemisah.

$ cat myfile 
ax5aa 
aa3ya 
fg7ds 
pp0dd 
aa1bb

$ sort -k 1.3,1.3 myfile 
pp0dd 
aa1bb
aa3ya 
ax5aa 
fg7ds 

halaman manual semacam:

[...] -k, --key = POS1 [, POS2] mulai kunci di POS1 (asal 1), akhiri di POS2 (akhir baris default) [...] POS adalah F [.C] [ OPTS], di mana F adalah nomor bidang dan C posisi karakter di lapangan; keduanya adalah asal 1. Jika tidak -t maupun -b berlaku, karakter dalam bidang dihitung dari awal spasi putih sebelumnya. OPTS adalah satu atau lebih opsi pemesanan satu huruf, yang mengesampingkan opsi pemesanan global untuk kunci itu. Jika tidak ada kunci yang diberikan, gunakan seluruh baris sebagai kunci.

Dengan --key = 1.3.1.3, Anda mengatakan bahwa hanya ada satu bidang (seluruh baris) dan Anda membandingkan posisi karakter ketiga dari bidang ini.

Franck
sumber