Apa Cnilai untuk LC_ALLdilakukan dalam sistem seperti Unix?
Saya tahu itu memaksa lokal yang sama untuk semua aspek tapi apa fungsinya C?
Apa Cnilai untuk LC_ALLdilakukan dalam sistem seperti Unix?
Saya tahu itu memaksa lokal yang sama untuk semua aspek tapi apa fungsinya C?
Jawaban:
Ini memaksa aplikasi untuk menggunakan bahasa default untuk output:
$ LC_ALL=es_ES man
¿Qué página de manual desea?
$ LC_ALL=C man
What manual page do you want?
dan memaksa sortir menjadi byte-wise:
$ LC_ALL=en_US sort <<< $'a\nb\nA\nB'
a
A
b
B
$ LC_ALL=C sort <<< $'a\nb\nA\nB'
A
B
a
b
LC_ALLadalah variabel lingkungan yang menimpa semua pengaturan lokalisasi lainnya ( kecuali $LANGUAGEdalam 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 $LANGpreferensi Anda dengan nilai yang mengidentifikasi wilayah Anda (seperti fr_CH.UTF-8jika Anda berada di Swiss berbahasa Perancis, menggunakan UTF-8). LC_xxxVariabel individual mengesampingkan aspek tertentu. LC_ALLmenimpa mereka semua. The localeperintah, saat dipanggil tanpa argumen memberikan ringkasan dari pengaturan saat ini.
Misalnya, pada sistem GNU, saya mendapatkan:
$ locale
LANG=en_GB.UTF-8
LANGUAGE=
LC_CTYPE="en_GB.UTF-8"
LC_NUMERIC="en_GB.UTF-8"
LC_TIME="en_GB.UTF-8"
LC_COLLATE="en_GB.UTF-8"
LC_MONETARY="en_GB.UTF-8"
LC_MESSAGES="en_GB.UTF-8"
LC_PAPER="en_GB.UTF-8"
LC_NAME="en_GB.UTF-8"
LC_ADDRESS="en_GB.UTF-8"
LC_TELEPHONE="en_GB.UTF-8"
LC_MEASUREMENT="en_GB.UTF-8"
LC_IDENTIFICATION="en_GB.UTF-8"
LC_ALL=
Saya dapat mengganti pengaturan individual dengan misalnya:
$ LC_TIME=fr_FR.UTF-8 date
jeudi 22 août 2013, 10:41:30 (UTC+0100)
Atau:
$ LC_MONETARY=fr_FR.UTF-8 locale currency_symbol
€
Atau menimpa segalanya dengan LC_ALL.
$ LC_ALL=C LANG=fr_FR.UTF-8 LC_MESSAGES=fr_FR.UTF-8 cat /
cat: /: Is a directory
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 Clokal 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 dari ahingga z, Anda harus mengatur LC_ALL=C.
Pada sistem GNU, LC_ALL=Cdan LC_ALL=POSIX(atau LC_MESSAGES=C|POSIX) menimpa $LANGUAGE, sementara LC_ALL=anything-elsetidak.
Beberapa kasus di mana Anda biasanya perlu mengatur LC_ALL=C:
sort -uatau sort ... | uniq.... Di banyak lokal selain C, pada beberapa sistem (terutama yang GNU), beberapa karakter memiliki urutan penyortiran yang sama . sort -utidak 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 (yang Cdijamin lokal).=operator yang patuh POSIX expratau ==operator yang patuh POSIX awk( mawkdan gawkbukan 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, gunakan grep '[[:alpha:]]'dan jangan modifikasi LC_ALL. Tetapi jika Anda ingin mencocokkan a-zA-Zkarakter ASCII, Anda perlu salah satu LC_ALL=C grep '[[:alpha:]]'atau LC_ALL=C grep '[a-zA-Z]'¹. [a-z]cocok dengan karakter yang mengurutkan setelah adan sebelumnya z(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 seperti bashpola, dapat menyertakan [B-Z]atau [A-Y]. Di banyak tempat UTF-8 (termasuk en_US.UTF-8pada sebagian besar sistem), [a-z]akan menyertakan huruf latin dari ahingga ydengan diakritik tetapi bukan huruf-huruf dari z(karenazmacam sebelum mereka) yang saya tidak bisa bayangkan akan menjadi apa yang Anda inginkan (mengapa Anda ingin memasukkan édan tidak ź?).aritmatika floating point di ksh93. ksh93menghormati decimal_pointpengaturan dalam LC_NUMERIC. Jika Anda menulis skrip yang berisi a=$((1.2/7)), skrip tersebut akan berhenti berfungsi ketika dijalankan oleh pengguna yang lokalnya memiliki koma sebagai pemisah desimal:
$ ksh93 -c 'echo $((1.1/2))'
0.55
$ LANG=fr_FR.UTF-8 ksh93 -c 'echo $((1.1/2))'
ksh93: 1.1/2: arithmetic syntax error
Maka Anda membutuhkan hal-hal seperti:
#! /bin/ksh93 -
float input="$1" # get it as input from the user in his locale
float output
arith() { typeset LC_ALL=C; (($@)); }
arith output=input/1.2 # use the dot here as it will be interpreted
# under LC_ALL=C
echo "$output" # output in the user's locale
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 di Clokal.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:
$ printf '%g\n' 1e-2
0,01
$ LC_ALL=C printf '%g\n' 1e-2
0.01
$ date +%b
août
$ LC_ALL=C date +%b
Aug
Itu juga berlaku untuk hal-hal seperti perbandingan kasus tidak sensitif (seperti dalam grep -i) dan konversi kasus ( awk's toupper(), dd conv=ucase...). Misalnya:
grep -i i
tidak dijamin cocok Idengan di lokal pengguna. Di beberapa lokal Turki misalnya, tidak seperti huruf besar iadalah İ(perhatikan titik) di sana dan lebih rendah-kasus Iadalah ı(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.big5hkscslokal (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:
LC_ALL=C grep '[[:alpha:]]'
atau
LC_ALL=C grep '[a-zA-Z]'
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 dari A. 䨝adalah 0x96 0x41, dan A0x41 seperti di ASCII. Jadi kami LC_ALL=C grep '[a-zA-Z]'akan mencocokkan pada baris-baris yang berisi karakter-karakter itu karena akan salah menafsirkan urutan byte tersebut.
LC_COLLATE=C grep '[A-Za-z]'
akan bekerja, tetapi hanya jika LC_ALLtidak ditentukan (yang akan menimpa LC_COLLATE). Jadi Anda akhirnya harus melakukan:
grep '[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]'
jika Anda ingin mencari huruf bahasa Inggris di file yang dikodekan dalam pengkodean lokal.
CLokal 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 di Clokal. 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.
Cadalah lokal default, "POSIX" adalah alias dari "C". Saya kira "C" berasal dari ANSI-C. Mungkin ANSI-C mendefinisikan lokal "POSIX".
Cnama 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:
export LC_ALL=en_US.UTF-8
printf %b $(printf '\\U%08x\\n' $(seq $((0x11)) $((0x10ffff))))|grep -a '[a-z]'|wc -l
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.
export LC_ALL=en_US.UTF-8
for ((i=1;i<=0x1fffff;i++));do
x=$(printf %04x $i)
[[ $x = @(000a|d800|db7f|db80|dbff|dc00|dfff) ]]&&continue
printf %b \\U$x\\n
done|sort -c
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.
export LC_ALL=en_US.UTF-8
for ((i=0xb;i<=0xd7fe;i++));do
printf %b $(printf '\\U%08x\\n' $((i+1)) $i)|sort -c 2>/dev/null&&echo $i
done
(Contoh-contoh di atas digunakan %bkarena printf \\U25menghasilkan 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 sortatau GNU sort) tetapi ② pertama di Ubuntu:
export LC_ALL=en_US.UTF-8;printf %s\\n ② ①|sort
Ini mencetak tiga baris di OS X (menggunakan OS X sortatau GNU sort) tetapi satu baris di Ubuntu:
export LC_ALL=en_US.UTF-8;printf %b\\n \\u0d4c \\u0d57 \\u0d46\\u0d57|sort -u
Tampaknya LC_COLLATEmengontrol "urutan abjad" yang digunakan oleh ls, juga. Lokal AS akan mengurutkan sebagai berikut:
a.C
aFilename.C
aFilename.H
a.H
pada dasarnya mengabaikan periode. Anda mungkin lebih suka:
a.C
a.H
aFilename.C
aFilename.H
Tentu saja saya lakukan. Pengaturan LC_COLLATEuntuk Cmencapai ini. Perhatikan bahwa ini juga akan mengurutkan huruf kecil setelah semua huruf besar:
A.C
A.H
AFilename.C
a.C
a.H
xclockperingatan (Missing charsets in String to FontSet conversion), akan lebih baik jika Anda akan menggunakanLC_ALL=C.UTF-8untuk menghindari masalah dengan cyrillic. Untuk mengatur variabel lingkungan ini, Anda harus menambahkan baris berikut di akhir~/.bashrcfile -export LC_ALL=C.UTF-8