Di mana baris `uniq` atau` sort -u` saya hilang, dengan beberapa karakter unicode

10

Apa yang terjadi dalam cuplikan kode berikut? Saya tidak mendapatkan hasil yang saya harapkan.

Saya pikir itu adalah bug, tetapi itu terjadi untuk 2 program yang berbeda (uniq dan urutkan), jadi saya curiga ada hubungannya dengan ... well, saya tidak tahu apa .. maka pertanyaannya.

3 (dari 4) contoh pertama berfungsi, tetapi yang ke-4 gagal !.

Saya mengharapkan perilaku yang sama untuk setiap dan semua karakter.
yaitu. untuk mencetak 2 baris (dari 3 baris input) ... tetapi dalam kasus ke-4, saya hanya mendapatkan 1 baris (untuk keduanya sort -udan uniq); dua kaleng identik menghilang begitu saja!

Saya telah mengonversi keluaran '\ n' ke ruang untuk tampilan yang kompak.

Saya menggunakan uniq dan menyortir dari (GNU coreutils) 7.4 ... berjalan di Ubuntu 10.04.3 LTS desktop.

Naskah:

{
  locale -k LC_COLLATE
  echo
  for c1 in x 〼 ;do 
    for c2 in z 〇 ;do 
      echo -n "asis   : "; echo -e "$c1\n$c2\n$c2"          |tr '\n' ' ';echo
      echo -n "uniq   : "; echo -e "$c1\n$c2\n$c2" |uniq    |tr '\n' ' ';echo
      echo -n "sort -u: "; echo -e "$c1\n$c2\n$c2" |sort -u |tr '\n' ' ';echo
      echo
    done
    echo
  done
}

Hasil:

collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=2081
collate-codeset="UTF-8"

asis   : x z z 
uniq   : x z 
sort -u: x z 

asis   : x 〇 〇 
uniq   : x 〇 
sort -u: 〇 x 


asis   : 〼 z z 
uniq   : 〼 z 
sort -u: 〼 z 

asis   : 〼 〇 〇 
uniq   : 〼 
sort -u: 〼 

# In the last example (of 4) where did the '〇' go? .. U+3007 IDEOGRAPHIC NUMBER ZERO
#
Peter.O
sumber
Harap dicatat .. Untuk membuatnya cukup jelas. sortsendirian (tanpa opsi -u ) ... tidak melahap karakter .. Apa yang masuk, keluar ... Namun, seperti yang dapat diharapkan oleh penjelasan Gilles tentang karakter unicode "eksotis" yang memiliki nilai kanonik yang sama , ini karakter tidak disortir, selain itu mereka output sebagai kelompok FIFO yang tidak disortir ke "atas" keluaran sortir ... Jadi sebenarnya ada dua masalah di sini: 1. Karakter tidak disortir karena mungkin "naif" "Diharapkan, dan 2. Fitur" unik "dari keduanya sortdan uniqkehilangan data (dalam beberapa kasus).
Peter.O
Pembaruan: Seperti yang disebutkan oleh Gilles (saat penyortiran khusus-lokal tidak penting, dan urutan karakter cocok), sort -udan uniqberfungsi dengan baik dengan: LC_COLLATE=C; echo -e "〼\n〇\n〇" |sort -u(atau |uniq)
Peter.O

Jawaban:

11

Versi singkat: collation tidak benar-benar berfungsi di utilitas baris perintah.

Versi yang lebih panjang: fungsi dasar untuk membandingkan dua string strcoll. Deskripsi ini tidak terlalu membantu, tetapi metode operasi konseptualnya adalah untuk mengubah kedua string menjadi bentuk kanonik, dan kemudian membandingkan kedua bentuk kanonik. Fungsi strxfrmmembangun bentuk kanonik ini.

Mari kita amati bentuk kanonik dari beberapa string (dengan GNU libc, di bawah Debian squeeze):

$ export LC_ALL=en_US.UTF-8
$ perl -C255 -MPOSIX -le 'print "$_ ", unpack("h*", strxfrm($_)) foreach @ARGV' b a A à 〼 〇
b d010801020
a c010801020
A c010801090
à 101010102c6b
〼 101010102c6b102c6b102c6b
〇 101010102c6b102c6b102c6b

Seperti yang Anda lihat, 〼 dan 〇 memiliki bentuk kanonik yang sama. Saya pikir itu karena karakter ini tidak disebutkan dalam tabel susunan en_US.UTF-8lokal. Namun, mereka hadir di lokal Jepang.

$ export LC_ALL=ja_JP.UTF-8
$ perl -C255 -MPOSIX -le 'print "$_ ", unpack("h*", strxfrm($_)) foreach @ARGV' 〼 〇 
〼 303030
〇 3c9b

Kode sumber untuk data lokal (dalam pemerasan Debian) ada di /usr/share/i18n/locales/en_US, yang termasuk /usr/share/i18n/locales/iso14651_t1_common. File ini tidak memiliki entri untuk U3007atau U303C, juga tidak termasuk dalam rentang apa pun yang dapat saya temukan.

Saya tidak terbiasa dengan aturan untuk membangun susunan susunan , tetapi dari apa yang saya mengerti, frasa yang relevan adalah

Simbol UNDEFINED harus ditafsirkan sebagai termasuk semua nilai set karakter kode tidak ditentukan secara eksplisit atau melalui simbol ellipsis. (...) Jika tidak ada simbol UNDEFINED yang ditentukan, dan rangkaian karakter kode saat ini berisi karakter yang tidak ditentukan dalam bagian ini, utilitas akan mengeluarkan pesan peringatan dan menempatkan karakter tersebut di akhir urutan susunan karakter.

Sepertinya Glibc malah mengabaikan karakter yang tidak ditentukan. Saya tidak tahu apakah ada kekurangan pemahaman saya tentang spesifikasi POSIX, jika saya melewatkan sesuatu dalam definisi lokal Glibc, atau jika ada bug di kompiler lokal Glibc.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
@Gilles: Terima kasih atas penjelasan yang informatif dan terperinci .. Masuk akal sekarang, tapi saya masih bertanya-tanya, bagaimana cara "aman" menggunakan semacam .. Saya tidak mencari jenis "sensitif lokal", jadi kasar semacam akan dilakukan ... Apakah ada solusi cepat untuk ini? ... dan saya akan secara bertahap memahami ini, tetapi itu tidak akan terjadi 'dalam semalam' ... misalnya .. my / usr / share / i18n / charmaps / UTF-8 berisi referensi untuk kedua karakter tersebut , tetapi berada dalam definisi UTF-8 (?) ini tampaknya tidak membantu ... Oh, seperti apa kehidupan tanpa misteri kecilnya. :) ...
Peter.O
1
@ Fred charmaps/UTF-8tidak mengatakan apapun tentang collation, itu locales/en_USyang penting. Aturan pertama LC_COLLATEadalah: jangan gunakan LC_COLLATE. Di lokal C (= POSIX), collation adalah wajar (hanya didasarkan pada nilai karakter numerik).
Gilles 'SANGAT berhenti menjadi jahat'
2
Aspek penyortiran dan unik bekerja dengan baik ketika didahului oleh LC_COLLATE=C... terima kasih ...
Peter.O
1
Bukannya collation tidak berfungsi di utilitas tetapi bahwa glibc locales didesain dengan buruk. Perilaku itu (saat ini, tetapi lihat austingroupbugs.net/view.php?id=1070 ) diizinkan oleh POSIX, tetapi disayangkan dan tidak diinginkan.
Stéphane Chazelas
6

Untuk "dengan aman" sortstring Unicode, mungkin lihat msort:

[...] Msort memberikan fleksibilitas yang lebih besar dalam memilih bidang utama, lebih banyak jenis perbandingan, kemampuan untuk menggunakan aturan pengumpulan dari berbagai tempat pada kunci yang berbeda, kemampuan untuk menangani angka dalam sistem angka non-Barat, dan berbagai pilihan lain yang kurang di GNU sort dan BSD sort. Sedangkan msort memahami Unicode, pengurutan GNU dan pengurutan BSD tidak. [...]

http://www.billposer.org/Software/msort.html

sampai
sumber
@til: Terima kasih telah membuat saya sadar msort. GUI opsional membuat pengantar sedikit lebih mudah untuk merasakan apa yang ditawarkan. Mampu menyalin perintah yang dihasilkan sangat berguna ... Dan ya, itu mengurutkan karakter unicode, tetapi (jangan Anda hanya suka "tetapi":) ... tetapi tidak memiliki opsi unik : (... seperti yang disebutkan di tautan yang Anda poskan: Capabilities of GNU sort and BSD sort lacking in msort are the ability to merge files without sorting them (the --merge option) and the ability to emit only the first of an equal run (the --unique option)...
Sortirnya