Apa perbedaan antara opsi --general-numeric-sort dan --numeric-sort di gnu sort

113

sortmenyediakan dua jenis urutan numerik. Ini dari halaman manual:

   -g, --general-numeric-sort
          compare according to general numerical value

   -n, --numeric-sort
          compare according to string numerical value

Apa bedanya?

Trenton
sumber
17
Perhatikan bahwa dokumentasi lengkapnya sortbukanlah manhalaman tetapi infohalaman ( info sort).
a3nm

Jawaban:

85

Urutan numerik umum membandingkan angka sebagai float, ini memungkinkan notasi ilmiah misalnya 1,234E10 tetapi lebih lambat dan dapat mengalami kesalahan pembulatan (1,2345678 bisa muncul setelah 1,2345679), urutan numerik hanyalah jenis alfabet biasa yang mengetahui 10 muncul setelah 9.

Lihat http://www.gnu.org/software/coreutils/manual/html_node/sort-invocation.html

'-g' '--general-numeric-sort' '--sort = general-numeric' Urutkan secara numerik, menggunakan fungsi C standar strtod untuk mengonversi awalan setiap baris menjadi bilangan floating point presisi ganda. Hal ini memungkinkan bilangan floating point ditentukan dalam notasi ilmiah, seperti 1.0e-34 dan 10e100. Lokal LC_NUMERIC menentukan karakter titik desimal. Jangan laporkan kesalahan overflow, underflow, atau konversi. Gunakan urutan penyusunan berikut: Garis yang tidak dimulai dengan angka (semua dianggap sama). NaN (nilai "Bukan Angka", dalam aritmatika floating point IEEE) dalam urutan yang konsisten tetapi bergantung pada mesin. Minus infinity. Bilangan hingga dalam urutan numerik menaik (dengan -0 dan +0 sama). Ditambah tak terbatas.

Gunakan opsi ini hanya jika tidak ada alternatif; ini jauh lebih lambat daripada --numeric-sort (-n) dan dapat kehilangan informasi saat mengonversinya ke floating point.

'-n' '--numeric-sort' '--sort = numeric' Urutkan secara numerik. Nomor dimulai setiap baris dan terdiri dari opsional kosong, tanda '-' opsional, dan nol atau lebih digit mungkin dipisahkan oleh ribuan pemisah, secara opsional diikuti oleh karakter titik desimal dan nol atau lebih digit. Angka kosong diperlakukan sebagai '0'. Lokal LC_NUMERIC menentukan karakter titik desimal dan pemisah ribuan. Secara default kosong adalah spasi atau tab, tetapi lokal LC_CTYPE dapat mengubahnya.

Perbandingannya tepat; tidak ada kesalahan pembulatan.

Baik awalan '+' maupun notasi eksponensial dikenali. Untuk membandingkan string tersebut secara numerik, gunakan opsi --general-numeric-sort (-g).

Martin Beckett
sumber
2
Terima kasih. Aneh bahwa halaman pria dan info tidak memiliki ini di dalamnya. Saya juga tidak tahu tentang gnu.org/software/coreutils/manual/html_node/index.html .
Trenton
6
Hal ini tidak berhasil untuk saya. Saya menyortir file dengan kolom ketiga dengan konten seperti R1 R2 R10 R15. Menggunakan salah satu -k3.2natau -k3.2g, itu menyortir R10sebelumnya R2. Urutannya adalah leksikografik, bukan numerik. Saya berharap untuk memperlakukan bidang dari karakter kedua dan seterusnya sebagai angka.
Kaz
6
sortSpesifikasi utama @Kaz:. benar-benar Bizantium - singkatnya adalah: kosong sebelum bidang dianggap sebagai bagian dari bidang , jadi char. indeks 1 menunjuk ke kosong (pertama) sebelum field, bukan karakter pertama sebenarnya dari field. Akhiran karakter. indeks dengan buntuk memperbaiki masalah ini, yaitu: -k 3.2bn,3(perhatikan bahwa opsi global tidak berfungsi dalam kasus ini). Perhatikan juga penambahan , yang memastikan bahwa hanya kolom ke-3 yang digunakan - tanpa indeks kolom ke-2, sisa dari keseluruhan baris akan digunakan. -b,3
mklement0
11

Anda harus berhati-hati dengan tempat Anda. Misalnya, Anda mungkin bermaksud untuk mengurutkan angka mengambang (seperti 2.2) sedangkan lokal Anda mungkin mengharapkan penggunaan koma (seperti 2,2).

Seperti yang dilaporkan di forum ini , Anda mungkin mendapatkan hasil yang salah menggunakan tanda -n atau -g.

Dalam kasus saya, saya menggunakan:

LC_ALL=C sort -k 6,6n file

untuk mengurutkan kolom ke-6 yang berisi:

2.5
3.7
1.4

untuk mendapatkan

1.4
2.5
3.7
JFL
sumber
2
Bahkan dengan LANG = C, saya tidak bisa -nmengenali koma sebagai pemisah ribuan - "1.000" diperlakukan sama dengan "1".
Scott
1
Itu harus LC_ALL = C.
Stuart P. Bentley
@ Scott: Memang, ribuan pemisah TIDAK dikenali: sortmenggunakan logika awalan-terpanjang : bagian terpanjang dari baris / kunci yang dikenali sebagai angka digunakan; di lokal yang digunakan .sebagai karakter radix, itu akan berhenti membaca di ,.
mklement0
@ StuartP.Bentley: LC_ALL=Cmemang pilihan yang paling tepat; Namun, jika LC_ALLkebetulan tidak memasang taruhan, LANG=Cakan berhasil juga.
mklement0
1
Poin bagus, tetapi LANG=C sort -k 6,6n filelebih sederhana dan juga melokalkan efek pengaturan variabel lingkungan LANGke perintah tertentu.
mklement0
0

Selain jawaban yang diterima yang menyebutkan -gbolehkan notasi ilmiah , saya ingin menunjukkan bagian yang paling mungkin menyebabkan perilaku yang tidak diinginkan.

Dengan -g:

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=en_US.UTF-8 sort -g myfile
baa
--inf
--inf  
--inf- 
--inf--
--inf-a
--nnf
nnf--
   nnn  
tnan
zoo
   naN
Nana
nani lol
-inf
-inf--
-11
-2
-1
1
+1
2
+2
0xa
11
+11
inf

Lihatlah zoo, tiga hal penting di sini:

  • Garis dimulai dengan NAN(misalnya Nanadan nani lol) atau -INF(tanda hubung tunggal, bukan --INF) pindah ke akhir tetapi sebelum digit. Sedangkan INFpindah ke angka terakhir setelahnya karena artinya tak terhingga .

  • The NAN,, INFdan -INFtidak peka huruf besar / kecil .

  • Garis selalu mengabaikan spasi dari kedua sisi NAN, INF, -INF (terlepas dari LC_CTYPE). Alfabet lain mungkin mengabaikan spasi kosong dari kedua sisi tergantung pada lokal LC_COLLATE(mis. LC_COLLATE=fr_FR.UTF-8Abaikan tapi LC_COLLATE=us_EN.UTF-8jangan abaikan).

Jadi, jika Anda mengurutkan alfanumerik sewenang-wenang, Anda mungkin tidak mau -g. Jika Anda benar-benar membutuhkan perbandingan notasi ilmiah -g, maka Anda mungkin ingin mengekstrak data alfabet dan numerik dan melakukan perbandingan secara terpisah .

Jika Anda hanya membutuhkan nomor biasa (misalnya 1, -1) sortir, dan dirasa 0x/E/+ sortingtidak penting, gunakan -nsecukupnya saja:

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=en_US.UTF-8 sort -n myfile
-1000
-22
-13
-11
-010
-10
-5
-2
-1
-0.2
-0.12
-0.11
-0.1
0x1
0x11
0xb
+1
+11
+2
-a
-aa
--aa
-aaa
-b
baa
BAA
bbb
+ignore
inf
-inf
--inf
--inf  
--inf- 
--inf--
-inf--
--inf-a
   naN
Nana
nani lol
--nnf
nnf--
   nnn  
None         
uum
Zero cool
-zzz
1
1.1
1.234E10
5
11

Salah satu dari -gatau -n, waspadai efek lokal . Anda mungkin ingin menentukan LC_NUMERICsebagai us_EN.UTF-8 untuk menghindari fr_FR.UTF-8 semacam -dengan floating nomor gagal :

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=fr_FR.UTF-8 sort -n myfile
-10
-5
-2
-1
-1.1
-1.2
-0.1
-0.11
-0.12
-0.2
-a
+b
middle
-wwe
+zoo
1
1.1

Dengan LC_NUMERIC=en_US.UTF-8:

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=en_US.UTF-8 sort -n myfile
-10
-5
-2
-1.2
-1.1
-1
-0.2
-0.12
-0.11
-0.1
-a
+b
middle
-wwe
+zoo
1
1.1

Atau LC_NUMERIC=us_EN.UTF-8untuk berkelompok +|-|spacedengan alpha:

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=us_EN.UTF-8 sort -n myfile
-0.1
    a
    b
 a
 b
+b
+zoo
-a
-wwe
middle
1

Anda mungkin ingin menentukan localekapan menggunakan sortjika ingin menulis skrip portabel.

Buah
sumber