Apa C
nilai untuk LC_ALL
dilakukan dalam sistem seperti Unix?
Saya tahu itu memaksa lokal yang sama untuk semua aspek tapi apa fungsinya C
?
environment-variables
locale
jcubic
sumber
sumber
xclock
peringatan (Missing charsets in String to FontSet conversion
), akan lebih baik jika Anda akan menggunakanLC_ALL=C.UTF-8
untuk menghindari masalah dengan cyrillic. Untuk mengatur variabel lingkungan ini, Anda harus menambahkan baris berikut di akhir~/.bashrc
file -export LC_ALL=C.UTF-8
Jawaban:
Ini memaksa aplikasi untuk menggunakan bahasa default untuk output:
dan memaksa sortir menjadi byte-wise:
sumber
LC_ALL
adalah variabel lingkungan yang menimpa semua pengaturan lokalisasi lainnya ( kecuali$LANGUAGE
dalam beberapa keadaan ).Berbagai aspek lokalisasi (seperti seribu pemisah atau karakter titik desimal, set karakter, urutan penyortiran, bulan, nama hari, bahasa atau pesan aplikasi seperti pesan kesalahan, simbol mata uang) dapat diatur menggunakan beberapa variabel lingkungan.
Anda biasanya akan menetapkan
$LANG
preferensi Anda dengan nilai yang mengidentifikasi wilayah Anda (sepertifr_CH.UTF-8
jika Anda berada di Swiss berbahasa Perancis, menggunakan UTF-8).LC_xxx
Variabel individual mengesampingkan aspek tertentu.LC_ALL
menimpa mereka semua. Thelocale
perintah, saat dipanggil tanpa argumen memberikan ringkasan dari pengaturan saat ini.Misalnya, pada sistem GNU, saya mendapatkan:
Saya dapat mengganti pengaturan individual dengan misalnya:
Atau:
Atau menimpa segalanya dengan LC_ALL.
Dalam skrip, jika Anda ingin memaksakan pengaturan tertentu, karena Anda tidak tahu pengaturan apa yang dipaksakan pengguna (mungkin juga LC_ALL), opsi terbaik, teraman dan umumnya satu-satunya adalah memaksa LC_ALL.
The
C
lokal adalah lokal khusus yang dimaksudkan untuk menjadi lokal yang paling sederhana. Anda juga bisa mengatakan bahwa sementara lokal lainnya untuk manusia, lokal C adalah untuk komputer. Dalam C locale, karakter adalah byte tunggal, charsetnya adalah ASCII (well, tidak diharuskan, tetapi dalam praktiknya akan ada di sistem yang sebagian besar dari kita akan pernah menggunakan), urutan penyortiran didasarkan pada nilai byte, bahasa biasanya US English (meskipun untuk pesan aplikasi (yang bertentangan dengan hal-hal seperti nama bulan atau hari atau pesan oleh pustaka sistem), itu berdasarkan kebijaksanaan penulis aplikasi) dan hal-hal seperti simbol mata uang tidak didefinisikan.Pada beberapa sistem, ada perbedaan dengan lokal POSIX di mana misalnya urutan sortir untuk karakter non-ASCII tidak ditentukan.
Anda biasanya menjalankan perintah dengan LC_ALL = C untuk menghindari pengaturan pengguna untuk mengganggu skrip Anda. Misalnya, jika Anda ingin
[a-z]
mencocokkan 26 karakter ASCII daria
hinggaz
, Anda harus mengaturLC_ALL=C
.Pada sistem GNU,
LC_ALL=C
danLC_ALL=POSIX
(atauLC_MESSAGES=C|POSIX
) menimpa$LANGUAGE
, sementaraLC_ALL=anything-else
tidak.Beberapa kasus di mana Anda biasanya perlu mengatur
LC_ALL=C
:sort -u
atausort ... | uniq...
. Di banyak lokal selain C, pada beberapa sistem (terutama yang GNU), beberapa karakter memiliki urutan penyortiran yang sama .sort -u
tidak melaporkan garis unik, tetapi satu dari setiap kelompok garis yang memiliki urutan penyortiran yang sama. Jadi jika Anda menginginkan garis yang unik, Anda memerlukan lokal tempat karakter byte dan semua karakter memiliki urutan penyortiran yang berbeda (yangC
dijamin lokal).=
operator yang patuh POSIXexpr
atau==
operator yang patuh POSIXawk
(mawk
dangawk
bukan POSIX dalam hal itu), yang tidak memeriksa apakah dua string identik tetapi apakah mereka mengurutkan sama.grep
. Jika Anda bermaksud mencocokkan huruf dalam bahasa pengguna, gunakangrep '[[:alpha:]]'
dan jangan modifikasiLC_ALL
. Tetapi jika Anda ingin mencocokkana-zA-Z
karakter ASCII, Anda perlu salah satuLC_ALL=C grep '[[:alpha:]]'
atauLC_ALL=C grep '[a-zA-Z]'
¹.[a-z]
cocok dengan karakter yang mengurutkan setelaha
dan sebelumnyaz
(meskipun dengan banyak API itu lebih rumit dari itu). Di tempat lain, Anda biasanya tidak tahu apa itu. Misalnya beberapa lokal mengabaikan kasus untuk mengurutkan sehingga[a-z]
dalam beberapa API sepertibash
pola, dapat menyertakan[B-Z]
atau[A-Y]
. Di banyak tempat UTF-8 (termasuken_US.UTF-8
pada sebagian besar sistem),[a-z]
akan menyertakan huruf latin daria
hinggay
dengan diakritik tetapi bukan huruf-huruf dariz
(karenaz
macam sebelum mereka) yang saya tidak bisa bayangkan akan menjadi apa yang Anda inginkan (mengapa Anda ingin memasukkané
dan tidakź
?).aritmatika floating point di
ksh93
.ksh93
menghormatidecimal_point
pengaturan dalamLC_NUMERIC
. Jika Anda menulis skrip yang berisia=$((1.2/7))
, skrip tersebut akan berhenti berfungsi ketika dijalankan oleh pengguna yang lokalnya memiliki koma sebagai pemisah desimal:Maka Anda membutuhkan hal-hal seperti:
Sebagai catatan:
,
pemisah desimal bertentangan dengan,
operator aritmatika yang dapat menyebabkan lebih banyak kebingungan.grep '<.*>'
untuk mencari baris yang mengandung<
,>
pasangan tidak akan berfungsi jika Anda berada di lokal UTF-8 dan input dikodekan dalam set karakter 8-bit byte tunggal seperti iso8859-15. Itu karena.
hanya karakter yang cocok dan karakter non-ASCII di iso8859-15 yang cenderung tidak membentuk karakter yang valid di UTF-8. Di sisi lain,LC_ALL=C grep '<.*>'
akan berfungsi karena nilai byte apa pun membentuk karakter yang valid diC
lokal.Kapan saja di mana Anda memproses data input atau data output yang tidak dimaksudkan dari / untuk manusia. Jika Anda berbicara dengan pengguna, Anda mungkin ingin menggunakan konvensi dan bahasa mereka, tetapi misalnya, jika Anda menghasilkan beberapa angka untuk memberi makan beberapa aplikasi lain yang mengharapkan titik desimal gaya Inggris, atau nama bulan bahasa Inggris, Anda ingin atur LC_ALL = C:
Itu juga berlaku untuk hal-hal seperti perbandingan kasus tidak sensitif (seperti dalam
grep -i
) dan konversi kasus (awk
'stoupper()
,dd conv=ucase
...). Misalnya:tidak dijamin cocok
I
dengan di lokal pengguna. Di beberapa lokal Turki misalnya, tidak seperti huruf besari
adalahİ
(perhatikan titik) di sana dan lebih rendah-kasusI
adalahı
(perhatikan hilang dot).¹ Bergantung pada pengodean teks, itu belum tentu hal yang benar untuk dilakukan. Itu berlaku untuk set karakter UTF-8 atau byte tunggal (seperti iso-8859-1), tetapi tidak harus set karakter multibyte non-UTF-8.
Misalnya, jika Anda berada di
zh_HK.big5hkscs
lokal (Hong Kong, menggunakan varian Hong Kong dari pengkodean karakter Cina BIG5), dan Anda ingin mencari huruf bahasa Inggris di file yang dikodekan dalam rangkaian karakter itu, lakukan salah satu dari:atau
akan salah, karena dalam charset itu (dan banyak lainnya, tetapi hampir tidak digunakan sejak UTF-8 keluar), banyak karakter berisi byte yang sesuai dengan pengkodean ASCII dari karakter A-Za-z. Misalnya, semua
A䨝䰲丕乙乜你再劀劈呸哻唥唧噀噦嚳坽
(dan banyak lagi) mengandung penyandian dariA
.䨝
adalah 0x96 0x41, danA
0x41 seperti di ASCII. Jadi kamiLC_ALL=C grep '[a-zA-Z]'
akan mencocokkan pada baris-baris yang berisi karakter-karakter itu karena akan salah menafsirkan urutan byte tersebut.akan bekerja, tetapi hanya jika
LC_ALL
tidak ditentukan (yang akan menimpaLC_COLLATE
). Jadi Anda akhirnya harus melakukan:jika Anda ingin mencari huruf bahasa Inggris di file yang dikodekan dalam pengkodean lokal.
sumber
C
Lokal hanya diperlukan untuk mendukung "set karakter portabel" (ASCII 0-127), dan perilaku untuk karakter> 127 secara teknis tidak ditentukan . Dalam praktiknya, sebagian besar program akan memperlakukannya sebagai data buram dan meneruskannya seperti yang Anda gambarkan. Tetapi tidak semua: khususnya, Ruby dapat mencekik data char dengan byte> 127 jika berjalan diC
lokal. Jujur saya tidak tahu apakah itu secara teknis "sesuai", tapi kami sudah melihatnya di alam liar .perl
's\x{7FFFFFFFFFFFFFFF}
) dan sementara kisaran Unicode poin kode telah sewenang-wenang terbatas U + 10FFFF (karena keterbatasan desain UTF-16), beberapa alat masih mengenali / menghasilkan karakter 6 byte. Itulah yang saya maksudkan dengan 6 byte karakter. Dalam semantik Unix, satu karakter adalah satu codepoint. Anda lebih dari satu codepoint "karakter" yang lebih umum dirujuk sebagai cluster graphem disambiguate dari karakter.C
adalah lokal default, "POSIX" adalah alias dari "C". Saya kira "C" berasal dari ANSI-C. Mungkin ANSI-C mendefinisikan lokal "POSIX".sumber
C
nama lokal berasal dari "ANSI C".Sejauh yang saya tahu, OS X menggunakan urutan susunan titik kode di UTF-8 lokal, jadi ini merupakan pengecualian untuk beberapa poin yang disebutkan dalam jawaban oleh Stéphane Chazelas.
Ini mencetak 26 di OS X dan 310 di Ubuntu:
Kode di bawah ini tidak mencetak apa pun di OS X, menunjukkan bahwa input diurutkan. Enam karakter pengganti yang dihapus menyebabkan kesalahan urutan byte ilegal.
Kode di bawah ini tidak mencetak apa pun di OS X, yang menunjukkan bahwa tidak ada dua titik kode berurutan (setidaknya antara U + 000B dan U + D7FF) yang memiliki urutan susunan yang sama.
(Contoh-contoh di atas digunakan
%b
karenaprintf \\U25
menghasilkan kesalahan dalam zsh.)Beberapa karakter dan urutan karakter yang memiliki susunan susunan yang sama di sistem GNU tidak memiliki susunan susunan yang sama di OS X. Ini mencetak ① pertama di OS X (menggunakan OS X
sort
atau GNUsort
) tetapi ② pertama di Ubuntu:Ini mencetak tiga baris di OS X (menggunakan OS X
sort
atau GNUsort
) tetapi satu baris di Ubuntu:sumber
Tampaknya
LC_COLLATE
mengontrol "urutan abjad" yang digunakan oleh ls, juga. Lokal AS akan mengurutkan sebagai berikut:pada dasarnya mengabaikan periode. Anda mungkin lebih suka:
Tentu saja saya lakukan. Pengaturan
LC_COLLATE
untukC
mencapai ini. Perhatikan bahwa ini juga akan mengurutkan huruf kecil setelah semua huruf besar:sumber