Itu konsekuensi dari karakter-karakter yang memiliki urutan penyortiran yang sama.
Anda juga akan memperhatikan itu
sort -u << EOF
■
⅕
⅖
⅗
EOF
mengembalikan hanya satu baris.
Atau itu:
expr ■ = ⅕
mengembalikan true (seperti yang disyaratkan oleh POSIX).
Sebagian besar lokal yang dikirimkan dengan sistem GNU memiliki sejumlah karakter (dan bahkan urutan karakter (susun urutan)) yang memiliki urutan penyortiran yang sama. Dalam kasus orang-orang ■ itu, itu karena urutannya tidak ditentukan, dan karakter-karakter yang urutannya tidak didefinisikan pada akhirnya memiliki urutan penyortiran yang sama dalam sistem GNU. Ada karakter yang secara eksplisit didefinisikan sebagai memiliki urutan penyortiran yang sama seperti Ș dan Ş (meskipun tidak ada logika nyata atau konsistensi tentang bagaimana hal itu dilakukan).
Itulah sumber perilaku yang cukup mengejutkan dan palsu. Saya telah mengangkat masalah ini baru-baru ini di milis Austin (badan di belakang POSIX dan Spesifikasi UNIX Tunggal) dan diskusi masih berlangsung hingga 2015-04-03.
Dalam hal ini, apakah [y]
harus cocok dengan di x
mana x
dan y
mengurutkan yang sama tidak jelas bagi saya, tetapi karena ekspresi braket dimaksudkan untuk mencocokkan elemen penyusun, itu menunjukkan bahwa bash
perilaku tersebut diharapkan.
Bagaimanapun, saya kira [⅕-⅕]
atau setidaknya [⅕-⅖]
harus cocok ■
.
Anda akan melihat bahwa berbagai alat berperilaku berbeda. ksh93 berperilaku seperti bash
, GNU grep
atau sed
tidak. Beberapa cangkang lain memiliki perilaku yang berbeda, beberapa yash
bahkan lebih buggy.
Untuk memiliki perilaku yang konsisten, Anda memerlukan lokal di mana semua karakter diurutkan secara berbeda. C locale adalah yang khas. Namun karakter yang ditetapkan di C locale pada kebanyakan sistem adalah ASCII. Pada sistem GNU, Anda biasanya memiliki akses ke C.UTF-8
lokal yang dapat digunakan untuk bekerja pada karakter UTF-8.
Begitu:
(export LC_ALL=C.UTF-8; [[ ■ = [⅕⅖⅗] ]])
atau standar yang setara:
(export LC_ALL=C.UTF-8
case ■ in ([⅕⅖⅗]) true;; (*) false; esac)
harus mengembalikan false.
Alternatif lain adalah dengan menetapkan hanya LC_COLLATE
untuk C yang akan bekerja pada sistem GNU, tetapi tidak harus pada yang lain di mana ia bisa gagal untuk menentukan urutan penyortiran karakter multi-byte.
Satu pelajaran tentang hal itu adalah bahwa kesetaraan tidak sejelas gagasan seperti yang diharapkan orang ketika membandingkan string. Kesetaraan mungkin berarti, dari yang paling ketat hingga yang paling tidak ketat.
- Jumlah byte dan konstituen byte yang sama memiliki nilai yang sama.
- Jumlah karakter yang sama dan semua karakter adalah sama (misalnya, merujuk pada codepoint yang sama di rangkaian karakter saat ini).
- Kedua string memiliki urutan pengurutan yang sama sesuai dengan algoritma collation lokal (yaitu, a <b atau b> a tidak benar).
Sekarang, untuk 2 atau 3, yang mengasumsikan kedua string berisi karakter yang valid. Dalam UTF-8 dan beberapa pengkodean lainnya, beberapa urutan byte tidak membentuk karakter yang valid.
1 dan 2 tidak harus sama karena itu, atau karena beberapa karakter mungkin memiliki lebih dari satu kemungkinan penyandian. Itu biasanya kasus pengkodean stateful seperti ISO-2022-JP di mana A
dapat dinyatakan sebagai 41
atau 1b 28 42 41
( 1b 28 42
menjadi urutan untuk beralih ke ASCII dan Anda dapat memasukkan sebanyak yang Anda inginkan, yang tidak akan membuat perbedaan), meskipun saya tidak akan mengharapkan jenis-jenis penyandian itu masih digunakan, dan alat-alat GNU setidaknya secara umum tidak bekerja dengan benar.
Berhati-hatilah karena sebagian besar utilitas non-GNU tidak dapat menangani nilai 0 byte (karakter NUL di ASCII).
Mana yang definisi yang digunakan tergantung pada utilitas dan utilitas implementasi atau versi. POSIX tidak 100% jelas tentang hal itu. Di C locale, ketiganya setara. Di luar YMMV itu.