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
?
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
?
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_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 (seperti fr_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. The locale
perintah, 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 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 dari a
hingga z
, Anda harus mengatur LC_ALL=C
.
Pada sistem GNU, LC_ALL=C
dan LC_ALL=POSIX
(atau LC_MESSAGES=C|POSIX
) menimpa $LANGUAGE
, sementara LC_ALL=anything-else
tidak.
Beberapa kasus di mana Anda biasanya perlu mengatur LC_ALL=C
:
sort -u
atau sort ... | 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 (yang C
dijamin lokal).=
operator yang patuh POSIX expr
atau ==
operator yang patuh POSIX awk
( mawk
dan gawk
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, gunakan grep '[[:alpha:]]'
dan jangan modifikasi LC_ALL
. Tetapi jika Anda ingin mencocokkan a-zA-Z
karakter 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 a
dan 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 bash
pola, dapat menyertakan [B-Z]
atau [A-Y]
. Di banyak tempat UTF-8 (termasuk en_US.UTF-8
pada sebagian besar sistem), [a-z]
akan menyertakan huruf latin dari a
hingga y
dengan diakritik tetapi bukan huruf-huruf dari z
(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
menghormati decimal_point
pengaturan 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 C
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:
$ 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 I
dengan di lokal pengguna. Di beberapa lokal Turki misalnya, tidak seperti huruf besar i
adalah İ
(perhatikan titik) di sana dan lebih rendah-kasus I
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:
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 A
0x41 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_ALL
tidak 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.
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 di C
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".
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:
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 %b
karena printf \\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 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 sort
atau 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_COLLATE
mengontrol "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_COLLATE
untuk C
mencapai ini. Perhatikan bahwa ini juga akan mengurutkan huruf kecil setelah semua huruf besar:
A.C
A.H
AFilename.C
a.C
a.H
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