「LC_ALL = C」は何をしますか?


324

UnixライクなシステムでのC価値は何LC_ALLですか?

私はそれがすべての面で同じロケールを強制することを知っていますが、何をしCますか?


xclockwarning(Missing charsets in String to FontSet conversion)を使用LC_ALL=C.UTF-8して問題を解決する場合は、キリル文字に関する問題を回避するために使用することをお勧めします。この環境変数を設定するには、~/.bashrcファイルの最後に次の行を追加する必要がありますexport LC_ALL=C.UTF-8
fedotsoldier

@fedotsoldierあなたはおそらくあなたが質問をして自分で答えを出すべきだろう、私はそれが質問に関連しているとは思わない。それはあなたが抱えているさまざまな問題への答えです。
jcubic

ええ、あなたは正しい、大丈夫
fedotsoldier

回答:


209

アプリケーションが出力にデフォルト言語を使用するように強制します。

$ LC_ALL=es_ES man
¿Qué página de manual desea?

$ LC_ALL=C man
What manual page do you want?

ソートを強制的にバイト単位にします:

$ 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

20
良いexemplesための+1が、ステファンの答えにある重要な情報が欠けている...
オリヴィエ・デュラック

4
デフォルト言語とはどういう意味ですか?
ステファンシャゼル

2
はい、私は著者が錫で言うことをしないことを含め、彼が好きなことを何でもできると理解しています。事はです。LC_ALL = C(LC_COLLATE)の並べ替え順序が意味を持つ唯一の言語であるLC_ALL = Cの文字セットで正しく表現できる言語は、米国英語のみです。LC_ALL= C(LC_TIME)には英語の月名と曜日名があります。LC_ALL = CがLC_ALL = en LANGUAGE = enとは異なる言語でメッセージを返すアプリを見たことはありません。そうでない場合、プログラムに対してバグを報告する権利がありますか?(ここでは英語に翻訳されていないアプリについては説明していません)。
ステファンシャゼル14

2
問題は、「LC_ALL = Cの文字セットで正しく表現できる言語は米国英語のみです」です。これは通常、ナロー文字を使用するC / C ++プログラムでのみ当てはまりますが、それでも例外があります(ASCIIで見つかった文字と記号のみを使用する言語がいくつかあるため)。デフォルトの言語が英語ではないときにバグを報告すると、あなたは...偏屈なように見えます。
イグナシオバスケス-アブラムス14

3
英語(LANG = en_US.utf8を意味する)では、メッセージは文字列を引用するために“”などのUnicode文字を使用できることに注意してください。一方、LANG = Cでは、ASCIIのもの(二重引用符、逆引用符、およびアポストロフィ)のみが含まれます。
アンヘル

332

LC_ALL他のすべてのローカライズ設定をオーバーライドする環境変数です(特定の状況を除く$LANGUAGE)。

ローカライズのさまざまな側面(千単位の区切り文字または小数点文字、文字セット、ソート順、月、曜日名、言語、またはエラーメッセージ、通貨記号などのアプリケーションメッセージ)は、いくつかの環境変数を使用して設定できます。

通常$LANG、お住まいの地域を識別する値を使用して好みに設定します(fr_CH.UTF-8フランス語を話すスイスの場合、UTF-8を使用します)。個々のLC_xxx変数は特定の側面をオーバーライドします。LC_ALLそれらをすべてオーバーライドします。locale引数なしで呼ばれたコマンドは、現在の設定の概要を示します。

たとえば、GNUシステムでは、次のようになります。

$ 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=

たとえば、個々の設定をオーバーライドできます。

$ LC_TIME=fr_FR.UTF-8 date
jeudi 22 août 2013, 10:41:30 (UTC+0100)

または:

$ LC_MONETARY=fr_FR.UTF-8 locale currency_symbol
€

または、LC_ALLですべてをオーバーライドします。

$ LC_ALL=C LANG=fr_FR.UTF-8 LC_MESSAGES=fr_FR.UTF-8 cat /
cat: /: Is a directory

スクリプトで、特定の設定を強制する場合、ユーザーが強制した設定(おそらくLC_ALLも)がわからないため、最善かつ安全で一般的に唯一のオプションはLC_ALLを強制することです。

Cロケールは、最も単純なロケールであることを意味する特別なロケールです。また、他のロケールは人間用であるのに対し、Cロケールはコンピューター用であると言うこともできます。Cロケールでは、文字は1バイトで、文字セットはASCIIです(そうする必要はありませんが、実際にはほとんどの人が使用するシステムになります)。並べ替え順序はバイト値に基づいています。言語は通常、米国英語(アプリケーションメッセージ(月や曜日の名前やシステムライブラリによるメッセージなど)ではなく、アプリケーション作成者の裁量による)であり、通貨記号などは定義されていません。

一部のシステムでは、たとえば非ASCII文字のソート順が定義されていないPOSIXロケールとの違いがあります。

通常、LC_ALL = Cを指定してコマンドを実行し、ユーザーの設定がスクリプトに干渉しないようにします。あなたがしたい場合たとえば、[a-z]から26個のASCII文字と一致するaにはz、あなたが設定する必要がありますLC_ALL=C

GNUシステムでは、LC_ALL=CおよびLC_ALL=POSIX(またはLC_MESSAGES=C|POSIX)オーバーライドしますが$LANGUAGELC_ALL=anything-elseそうではありません。

通常設定する必要があるいくつかのケースLC_ALL=C

  • sort -uまたはsort ... | uniq...。C以外の多くのロケールでは、一部のシステム(特にGNUのもの)では、一部の文字のソート順は同じです。sort -u一意の行はレポートしませんが、並べ替え順序が等しい行の各グループの1つです。したがって、一意の行が必要な場合は、文字がバイトであり、すべての文字が異なる並べ替え順序を持つロケールが必要です(Cロケールはそれを保証します)。
  • 同じことが適用されるに=準拠したPOSIXのオペレータexpr==POSIX準拠したのオペレータawkS(mawkおよびgawkその点ではPOSIXされていない)、2つの文字列が同一であるが、それらが同じかどうかを並べ替えるかどうかを確認しません。
  • のような文字範囲grep。ユーザーの言語の文字と一致させる場合は、を使用しgrep '[[:alpha:]]'、変更しないでくださいLC_ALL。ただし、a-zA-ZASCII文字を一致させるには、LC_ALL=C grep '[[:alpha:]]'またはLC_ALL=C grep '[a-zA-Z]'¹のいずれかが必要です。前後に[a-z]ソートされる文字に一致します(ただし、多くのAPIではそれよりも複雑です)。他のロケールでは、一般にそれらが何であるかわかりません。たとえば、一部のロケールではソートの大文字と小文字が区別されないため、パターンなどの一部のAPI では、またはを含めることができます。(を含む多くのUTF-8ロケールではほとんどのシステムで)、からラテン文字が含まれますには発音区別符号ではなく、それらの(以来、az[a-z]bash[B-Z][A-Y]en_US.UTF-8[a-z]ayzz私は想像することができない彼らの前に並べ替え)は含めたいなぜあなたは(何をしたいだろうéし、ありませんź?)。
  • の浮動小数点演算ksh93ksh93decimal_point設定を尊重しますLC_NUMERIC。を含むスクリプトを記述a=$((1.2/7))した場合、ロケールの小数点にカンマが含まれるユーザーが実行すると動作しなくなります。

    $ 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
    

    次に、次のようなものが必要です。

    #! /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
    

    補足説明として、,小数点記号は,算術演算子と競合するため、さらに混乱を招く可能性があります。

  • 文字をバイトにする必要がある場合。現在、ほとんどのロケールはUTF-8ベースであるため、文字は1〜6バイトを使用できます。テキストユーティリティを使用してバイト単位のデータを処理する場合は、LC_ALL = Cを設定する必要があります。UTF-8データの解析にはコストがかかるため、パフォーマンスも大幅に向上します。
  • 前のポイントの帰結:入力がどの文字セットで書かれているかわからないが、ASCIIと互換性があると仮定できるテキストを処理するとき(事実上すべての文字セットがそうであるように)。たとえば、UTF-8ロケールで入力がiso8859-15のようなシングルバイトの8ビット文字セットでエンコードされている場合、grep '<.*>'を含む行を検索するに<>ペアは機能しません。これ.は、iso8859-15の文字のみに一致し、非ASCII文字はUTF-8で有効な文字を形成しない可能性が高いためです。一方、LC_ALL=C grep '<.*>'バイト値はCロケールで有効な文字を形成するため、機能します。
  • 入力データまたは出力データを処理するときはいつでも、人間を対象としたものではありません。ユーザーと話している場合は、その慣習と言語を使用することができますが、たとえば、英語スタイルの小数点または英語の月名を期待する他のアプリケーションにフィードするためにいくつかの数値を生成する場合は、 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
    

    これは、大文字と小文字を区別しない比較(などgrep -i)や大文字と小文字の変換(awk's toupper()dd conv=ucase...)などにも当てはまります。例えば:

    grep -i i
    

    Iユーザーのロケールで一致することが保証されていません。例えば、いくつかのトルコ語のロケールでは、大文字としてないiİ(ドットに注意)が存在し、小文字Iであるı(ドット抜けに注意します)。


¹テキストのエンコーディングによっては、必ずしも正しいこととは限りません。これはUTF-8またはシングルバイト文字セット(iso-8859-1など)で有効ですが、必ずしも非UTF-8マルチバイト文字セットではありません。

たとえば、zh_HK.big5hkscsロケール(香港、香港版のBIG5中国語文字エンコードを使用)で、その文字セットでエンコードされたファイルで英語の文字を探したい場合、次のいずれかを実行します。

LC_ALL=C grep '[[:alpha:]]'

または

LC_ALL=C grep '[a-zA-Z]'

その文字セット(および他の多くの、しかしUTF-8が登場して以来ほとんど使用されていない)では、多くの文字にA-Za-z文字のASCIIエンコードに対応するバイトが含まれているため、間違ってます。たとえば、すべてA䨝䰲丕乙乜你再劀劈呸哻唥唧噀噦嚳坽(およびそれ以上)のエンコーディングが含まれていますA0x96 0x41でありA、ASCIIのように0x41です。したがって、LC_ALL=C grep '[a-zA-Z]'これらのバイトシーケンスを誤って解釈するため、これらの文字を含む行で一致します。

LC_COLLATE=C grep '[A-Za-z]'

動作しますが、がLC_ALL設定されていない場合にのみ有効です(これによりがオーバーライドされますLC_COLLATE)だからあなたはやらなければならないことになるかもしれません:

grep '[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]'

ロケールのエンコーディングでエンコードされたファイルで英語の文字を探したい場合。


12
+1、それは最高の答えです(オーバーライドを指摘するなど)。しかし、イグナシオの答えの(いい)例が欠けている^^
オリビエデュラック

1
ちょっとした注意:Cロケールは「ポータブル文字セット」(ASCII 0-127)をサポートするためにのみ必要であり、chars> 127の動作は技術的に指定されていません。実際には、ほとんどのプログラムはそれらを不透明なデータとして扱い、説明したとおりに通過させます。ただし、すべてではありません。特に、Cロケールで実行している場合、Rubyはバイト数が127を超えるcharデータで停止することがあります。正直に言って、それが技術的に「適合」しているかどうかはわかりませんが、実際に見てきました。
アンドリュージャンケ

2
@AndrewJanke、はい。ポータブル文字セットは、ASCIIや0-127を意味しないことに注意してください。オースティングループのメーリングリストでは、「C」ロケール文字セットのプロパティがどうなるかについて多くの議論があり、一般的なコンセンサス(そして次の仕様で明らかにされる)は、その文字セットはバイトであり、8ビットの全範囲を網羅しています(ここで説明するプロパティを使用)。それまでの間、はい(バグとして、または仕様が十分に明示的でないため)多少の相違が生じる可能性があります。いずれにせよ、LC_ALL = Cが最も適切な動作を取得できます。
ステファンシャゼル

1
UTF-8のUnicodeコードポイントには最大4オクテット(またはバイト)を含めることができますが、一部のキャラクターには複数のコードポイントが必要であり、6オクテットよりも長いシーケンスになる可能性があります。
12431234123412341234123

1
@ 12431234123412341234123、元のUTF-8エンコーディングは、U + 7FFFFFFFまでカバー(6バイト、など13のバイトまで行くためにいくつかの拡張機能がありperl、S「は、\x{7FFFFFFFFFFFFFFF}Unicodeコードポイントの範囲を任意にU + 10FFFFに制限されているが)と(UTF-16の設計上の制限により)、いくつかのツールはまだ6バイト文字を認識/生成します。それが私が6バイト文字で意味したことです。Unixセマンティクスでは、1文字は1コードポイントです。あなたの複数のコードポイント「キャラクター」は、より一般的には、キャラクターから曖昧さをなくすためのグラフェンクラスターとして参照されます。
ステファンシャゼル

7

Cはデフォルトのロケールであり、「POSIX」は「C」のエイリアスです。「C」はANSI-Cから派生したと思います。たぶん、ANSI-Cは「POSIX」ロケールを定義しています。


CとUNIXの両方がはるかにANSI C.さかのぼる
からCVn

@MichaelKjörling:それで?ANSI以前のドキュメントを見てきましたが、ロケールがありませんでした。AT&Tベルラボでは、全員が英語を話しました。
MSalters

@MSalters C言語のANSI以前のドキュメントにはロケールが記載されていないという事実(ANSI以前のCにはロケールの概念がなかったことを意味する場合もしない場合もありますが、結局のところ、この言語はまだ、それはポイントの横にあります)は、Cロケール名が「ANSI C」に由来することを意味するものではありません。
CVn

2
@MichaelKjörling:ポイントがありません。ロケールが導入されたとき、「C」はすでに「ANSI C」を意味していました。過去のK&R Cを意味することは無関係です。
–MSalters

3

私が知る限り、OS XはUTF-8ロケールでコードポイントの照合順序を使用しているため、StéphaneChazelasの回答で言及されているポイントの一部は例外です。

OS Xでは26、Ubuntuでは310が印刷されます。

export LC_ALL=en_US.UTF-8
printf %b $(printf '\\U%08x\\n' $(seq $((0x11)) $((0x10ffff))))|grep -a '[a-z]'|wc -l

以下のコードは、OS Xでは何も印刷せず、入力がソートされていることを示しています。削除された6つのサロゲート文字により、不正なバイトシーケンスエラーが発生します。

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

以下のコードはOS Xで何も印刷しません。これは、同じ照合順序を持つ2つの連続したコードポイント(少なくともU + 000BとU + D7FFの間)がないことを示しています。

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

(上記の例は、zshでエラーが発生する%bため使用printf \\U25します。)

GNUシステムで同じ照合順序を持ついくつかの文字および文字シーケンスは、OS Xでは同じ照合順序を持ちません。これは、OS Xでは最初に(OS X sortまたはGNUを使用sort)①、Ubuntuでは最初に印刷されます。

export LC_ALL=en_US.UTF-8;printf %s\\n ② ①|sort

OS Xでは3行(OS X sortまたはGNUを使用sort)が印刷されますが、Ubuntuでは1行が印刷されます。

export LC_ALL=en_US.UTF-8;printf %b\\n \\u0d4c \\u0d57 \\u0d46\\u0d57|sort -u

なぜこの違いがあるのか​​誰にも分かりますか?
1.61803

3

LC_COLLATElsが使用する「アルファベット順」も制御しているようです。USロケールは次のようにソートされます。

a.C
aFilename.C
aFilename.H
a.H

基本的にピリオドを無視します。あなたが好むかもしれません:

a.C
a.H
aFilename.C
aFilename.H

確かにそうです。これLC_COLLATEC達成するための設定。すべての大文字の後に小文字もソートすることに注意してください。

A.C
A.H
AFilename.C
a.C
a.H
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.