ロケールと文字コード
同じコマンドなのにメッセージが英語になったり日本語になったり、sort の並び順が環境によって変わったり。その裏にあるのがロケールです。優先順位は選択肢を作りやすいので繰り返し問われます。なお、この学習環境で使えるロケールは C と C.UTF-8 と POSIX の3つだけです。
LC_ALL が最強、LANG が最弱
LC_ALL は個別の LC_* をまとめて上書きし、その個別指定が無い分野に LANG の値が使われます。
ターミナル
LANG=C.UTF-8
LC_TIME=C
# 時刻表示だけが C ロケール、それ以外は C.UTF-8
LC_ALL=C
# この一行で上の2つは両方とも無視され、すべて C ロケールになるスクリプトの中で出力を安定させたいときに LC_ALL=C を付ける習慣があるのは、この全部を強制的に上書きする性質を使っているからです。
| 変数 | 制御するもの |
|---|---|
LANG | すべての LC_* の既定値。個別指定が無ければこれ |
LC_ALL | すべての LC_* を強制的に上書きする |
LC_CTYPE | 文字の分類と大文字小文字の変換 |
LC_COLLATE | 文字列の照合順序。sort の並び順を決める |
LC_TIME | 日付と時刻の表示形式。曜日や月の名前 |
LC_MESSAGES | コマンドが出すメッセージの言語 |
LC_NUMERIC | 数値の書式。小数点や桁区切り。LC_MONETARY は通貨 |
locale は現在有効なロケール変数の一覧、locale -a は利用できるロケールの一覧、locale -k LC_TIME は指定した分類の詳細です。systemd 環境なら localectl status で全体の設定を見て、localectl set-locale で設定します。
sort の順序を決めるのは LC_COLLATE
LC_COLLATE=C ではバイト値そのままの順で並ぶため、大文字がすべて小文字より前に来ます。ASCII では A が 0x41、a が 0x61 だからです。一方 en_US.UTF-8 のような言語ロケールでは辞書順の規則が働き、大文字小文字を区別せずに並べたり記号を無視したりします。同じファイルを並べ替えても結果が違うので、スクリプトで並び順に依存するときはロケールを明示します。順序を決めるのは LC_CTYPE ではなく LC_COLLATE だ、という取り違えが定番の出題です。
Unicode は文字集合、UTF-8 は符号化方式
| 名前 | 説明 |
|---|---|
| ASCII | 7ビット。英数字と記号のみ。128文字 |
| ISO-8859-1 | 8ビット。西欧言語用に ASCII を拡張したもの |
| EUC-JP | UNIX 系で使われてきた日本語コード |
| Shift_JIS | Windows 系の日本語コード。2バイト目が ASCII と重なる範囲がある |
| Unicode | 世界中の文字に番号を振った文字集合そのもの |
| UTF-8 | Unicode の符号化方式。ASCII 互換で、日本語は1文字3バイトが基本 |
| UTF-16 | Unicode の符号化方式。基本的に1文字2バイト。ASCII 互換ではない |
UTF-8 では ASCII の範囲が1バイトのまま変わらないので、英数字だけのファイルはそのまま UTF-8 として読めます。
文字コードの変換は iconv
ターミナル
iconv -f EUC-JP -t UTF-8 old.txt > new.txt
iconv -l-f が変換元、-t が変換先、-l が使える文字コードの一覧、-o が出力先ファイル、-c が変換できない文字を捨てて続行する指定です。
日本語向けには nkf もよく使われます。-w で UTF-8 へ、-e で EUC-JP へ、-s で Shift_JIS へ、-g で文字コードの判別です。改行コードも変えられ、-Lu で LF、-Lw で CRLF になります。
ロケールの設定ファイル
Debian 系はシステム全体の既定を /etc/default/locale に、Red Hat 系と systemd は /etc/locale.conf に書きます。生成するロケールの一覧は /etc/locale.gen にあり、使う行のコメントを外してから locale-gen を実行すると、そのロケールのデータが生成されて locale -a に現れます。この2段構えが試験で問われます。
試験で狙われるところ
LC_ALL は最強で、設定されていると LANG も個別の LC_* も無視されます。LANG は最弱の既定値で、上書きする力を持ちません。sort の順序を決めるのは LC_COLLATE です。メッセージの言語は LC_MESSAGES、時刻の書式は LC_TIME です。そして locale -a は利用できるロケールの一覧、locale だけなら現在の設定値です。