$ locale charmap
UTF-8
Dalam lingkungan saya saat ini, set karakter adalah UTF-8, yaitu, karakter dikodekan dengan 1 hingga 4 byte per karakter (meskipun karena definisi asli dari UTF-8 memungkinkan kode karakter menunjukkan hingga 0x7fffffff, sebagian besar alat akan mengenali UTF- Urutan 8 byte hingga 6 byte).
Dalam set karakter itu, semua karakter dari Unicode tersedia, a a
dikodekan sebagai nilai byte 65, a 乕
sebagai 3 byte 228 185 149 dan é
sebagai urutan dua byte 195 169 misalnya.
$ printf 乕 | wc -mc
1 3
$ printf a | wc -mc
1 1
Sekarang:
$ export fr_FR.iso885915@euro
$ locale charmap
ISO-8859-15
Saya telah memodifikasi lingkungan saya, di mana set karakter sekarang ISO-8859-15 (hal-hal lain seperti bahasa, simbol mata uang, format tanggal juga telah dimodifikasi, kumpulan pengaturan regional tersebut disebut sebagai lokal ). Saya perlu memulai emulator terminal baru di lingkungan itu untuk mengadaptasi render karakternya ke lokal baru.
ISO-8859-15 adalah set karakter byte tunggal yang berarti hanya memiliki 256 karakter (sebenarnya bahkan lebih sedikit dari yang sebenarnya tercakup). Kumpulan karakter tertentu digunakan untuk bahasa Eropa Barat karena mencakup sebagian besar bahasa (dan simbol euro).
Ia memiliki a
karakter dengan nilai byte 65 seperti pada UTF-8 atau ASCII, ia juga memiliki é
karakter (seperti yang biasa digunakan dalam bahasa Prancis atau Spanyol misalnya) tetapi dengan nilai byte 233, ia tidak memiliki karakter 乕.
Di lingkungan itu, wc -c
dan wc -m
akan selalu memberikan hasil yang sama.
Di Ubuntu seperti pada kebanyakan sistem mirip Unix modern, standarnya biasanya UTF-8 karena hanya set karakter yang didukung (dan penyandian) yang mencakup seluruh jangkauan Unicode.
Pengkodean karakter multi-byte lain ada, tetapi tidak didukung dengan baik di Ubuntu dan Anda harus melalui lingkaran untuk dapat menghasilkan lokal dengan itu, dan jika Anda melakukannya, Anda akan menemukan bahwa banyak hal tidak bekerja dengan benar.
Jadi berlaku di Ubuntu, set karakter dapat berupa byte tunggal, atau UTF-8.
Sekarang, beberapa catatan lagi:
Dalam UTF-8, tidak semua urutan byte membentuk karakter yang valid. Sebagai contoh, semua karakter UTF-8 yang bukan ASCII dibentuk dengan byte yang semuanya memiliki bit ke-8, tetapi hanya karakter pertama yang memiliki bit ke-7.
Jika Anda memiliki urutan byte dengan set bit ke-8, tidak ada yang memiliki set bit ke-7, maka itu tidak dapat diterjemahkan ke karakter. Dan saat itulah Anda mulai mengalami masalah dan inkonsistensi karena perangkat lunak tidak tahu apa yang harus dilakukan dengan itu. Contohnya:
$ printf '\200\200\200' | wc -mc
0 3
$ printf '\200\200\200' | grep -q . || echo no
no
wc
dan grep
tidak menemukan karakter di sana tetapi:
$ x=$'\200\200\200' bash -c 'echo "${#x}"'
3
bash
menemukan 3. Ketika itu tidak dapat memetakan urutan byte ke karakter, ia menganggap setiap byte sebagai karakter.
Itu bisa menjadi lebih rumit karena ada titik-titik kode dalam Unicode yang tidak valid sebagai karakter, dan beberapa yang non-karakter , dan tergantung pada alatnya, pengkodean UTF-8 mereka mungkin atau mungkin tidak dianggap sebagai karakter.
Hal lain yang perlu dipertimbangkan adalah perbedaan antara karakter dan graphem, dan bagaimana mereka ditampilkan.
$ printf 'e\u301\u20dd\n'
é⃝
$ printf 'e\u301\u20dd' | wc -mc
3 6
Di sana, kami telah mengkode 3 karakter sebagai 6 byte yang dirender sebagai satu graphem, karena kami memiliki 3 karakter yang digabungkan menjadi satu (satu karakter dasar, sebuah aksen akut kombinasi, dan sebuah lingkaran penutup yang mengombinasikan).
Implementasi GNU wc
seperti yang ditemukan di Ubuntu memiliki -L
saklar untuk memberi tahu Anda lebar tampilan garis terluas di input:
$ printf 'e\u301\u20dd\n' | wc -L
1
Anda juga akan menemukan bahwa beberapa karakter menempati 2 sel dalam perhitungan lebar seperti 乕
karakter kami dari atas:
$ echo 乕 | wc -L
2
Kesimpulannya: dalam kata yang lebih liar, byte, karakter dan graphem tidak harus sama.