[Exp2010]文字コードあれこれ

◎文字コードあれこれ

ここでは EUC-JP, ShiftJIS, Unicode(UTF-8) で記述されたファイルを使用して

  • 文字コードを指定してファイルを表示する.
  • 文字コードを変換する

なんて事をしてみます.

ファイルを表示する.

ファイルを適切に表示するためにはファイルの文字コードに合わせて,

  1. 端末で表示する文字コード
  2. シェルの環境変数(LC_*, LANG)

をきちんと設定する必要があります *1.

端末で表示する文字コード

「表示にどの文字コードを使用するか」の設定は使用するターミナル によって異なります. 今回の実習で使用する gnome-terminal と mlterm について言語の切り替え方は以下の通りです.

  • gnome-terminal の場合
    • 上のメニュー内の「端末(T)」をクリック
    • 「文字コードの設定」より, 使用したい文字コードを選択

<URL:/~itpass/exp/fy2008/080620/practice/hiki-images/gnome-terminal-select-locale.png>

  • mlterm の場合
    • ターミナル上で Ctrl キーを押しながら右クリック
    • 出てきたメニュー内の「エンコーディング」で文字コードを選択

<URL:/~itpass/exp/fy2008/080620/practice/hiki-images/mlterm-select-locale.png>

その他のターミナルの場合については詳しくは触れません. それぞれのマニュアルを参照して下さい.

環境変数の確認・設定

多くのソフトウェアやプログラミング言語は, 使用する文字コードとともに, 国毎に異なる「単位, 記号, 日付, 通貨などの表記規則」を設定することで, データの表記を(場合によっては処理まで)行ないます. この表記規則のことをロケール(locale) と言います.

ロケールの切りかえは, 以下に示した環境変数で行ないます. 環境変数そのものについては 05/08 の実習「シェル--環境変数」を参照して下さい.

["LC_CTYPE"]
文字の種類とエンコーディングの指定
["LC_COLLATE"]
ソートのルールの指定
["LC_TIME"]
日付の書式の指定
["LC_NUMERIC"]
数字の書式の指定
["LC_MONETARY"]
通貨の書式の指定
["LC_MESSAGES"]
メッセージ表示に使用する言語の指定
["LC_PAPER"]
紙のサイズ
["LC_NAME"]
名前のフォーマット
["LC_ADDRESS"]
住所のフォーマット
["LC_TELEPHONE"]
電話番号のフォーマット
["LC_MEASUREMENT"]
長さの単位
["LC_IDENTIFICATION"]
これらの変数用のメタデータ.
["LC_ALL"]
上記 LC_CTYPE…LC_TIME を全て上書き(他の指定より, LC_ALL の設定を優先)します.
["LANGUAGE"]
LC_MESSAGES の設定を上書きします. GNU gettext だけ(?)が使用します. よって GNU gettext を内部で使用している全てのプログラムでは, LANGUAGE が使用されます.
["LANG"]
全ての LC_* 変数のデフォルト. LC_* が指定されていない場合には LANG の値が適用されます.
["LOC_PATH"]
言語のデータの置き場. 通常は /usr/share/locale に置かれる.

これらの変数の優先順位は

LANGUAGE > LC_ALL > LC_* > LANG

となっています*2. LC_* をひとつづつ設定するのは面倒ですので, 通常は LC_ALL もしくは LANG を設定します. ここでは LANG を設定してみましょう.

先ず 現在の言語設定を確認してみましょう. locale コマンドを引数無しで実行してみて下さい.

$ locale
LANG=ja_JP.UTF-8
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER="ja_JP.UTF-8"
LC_NAME="ja_JP.UTF-8"
LC_ADDRESS="ja_JP.UTF-8"
LC_TELEPHONE="ja_JP.UTF-8"
LC_MEASUREMENT="ja_JP.UTF-8"
LC_IDENTIFICATION="ja_JP.UTF-8"
LC_ALL=

などと表示されたと思います(環境によって結果は異なると思います). 上記の結果は "LANG" が "ja_JP.eucJP", LC_ALL が空白ですから, "LANG"" のみが設定されており, LC_* は全て LANG の値が用いられたのだと想像されます.

続いて システムでサポートされている言語を確認してみます. 以下のコマンドを実行してみて下さい.

$ locale -a
C
POSIX
ja_JP
ja_JP.eucjp
ja_JP.ujis
ja_JP.utf8
japanese
japanese.euc
  :

ujis は UNIX JIS の略*3で, 結局の所 EUC-JP を指します. よって, このシステムでは

  • EUC-JP: ja_JP.eucjp
  • UTF-8: ja_JP.utf8

がサポートされていることがわかります.

それぞれの文字コードを使用する際に環境変数 LANG に何を指定すれば良いかは, システムに依存しています. Debian の場合は,

  • EUC-JP
    • ja_JP.EUC-JP
    • ja_JP.eucJP
    • ja_JP.ujis
    • ja_JP.eucjp
  • UTF-8
    • ja_JP.UTF-8
    • ja_JP.utf8

です.

では, 試しに, 故意に間違った表示をさせてみましょう.

["実習その4:環境変数 LANG と端末の表示に使う文字コードを別の種類に変えて, \"man man\" の結果を故意に文字化けさせてみて下さい."]

確認したら, 元に戻しておきましょう - -;)

ファイルの表示

ここの実習に使用する以下のファイルを 手元の情報実験機にダウンロードしておいて下さい.

ダウンロードには wget というコマンドを用います.

$ wget http://itpass.scitec.kobe-u.ac.jp/~epa/exp/fy2010/100618/practice/text_sjis.txt
$ wget http://itpass.scitec.kobe-u.ac.jp/~epa/exp/fy2010/100618/practice/text_eucjp.txt
$ wget http://itpass.scitec.kobe-u.ac.jp/~epa/exp/fy2010/100618/practice/text_utf8.txt

これらのファイルをそれぞれ端末に表示させてみます. ここでは less や lv といった(高機能な)ページャを使用せず, cat コマンドでファイルの中身を端 末に表示させてみましょう.

$ cat text_sjis.txt
$ cat text_eucjp.txt
$ cat text_utf8.txt

どれか一つはそれなりに表示される筈ですが, 残り二つは悲しい結果になると思います. ちなみに表示が崩れてしまった場合には "reset" コマンドで端末表示をリセットしてみて下さい.

["実習その5:環境変数 LANG もしくは端末の表示に使う文字コードを切り替えることで, 上記三つのファイルをそれぞれ適切に表示して下さい."]

...できましたか?

文字コードの変換

「linux で作成したファイルを Windows で見ると文字化けがおきてしまう」と いった事は良くあります. 単なるテキストもさることながら, 苦心して作成し たプログラムや, 頑張って書いた論文などが文字化けの為に解読できない, と いうのは困りますよね?

ここでは, 文字コードの変換を行なってみましょう. UNIX 系の計算機における 代表的な文字コード変換プログラムには,

  • nkf
  • iconv (GNU の C ライブラリに含まれるプログラム)

などがあります. ここでは nkf を使って文字コードを変換してみます.

nkf (Network Kanji Filter)

nkf については, 以下の man からの引用を参照して下さい.

nkf はネットワークでメールやニュースの読み書きをするために作られた、漢
字コードの変換フィルタである. 

この nkf の特徴としては、入力漢字コード系の統計的な自動認識機能がある. 
このため、利用者は、入力漢字コード系が何であるかを知らなくても、出力漢
字コード系のみ指定すれば良いことになる. ただ、この判定機構は、理論的に
は完全ではないが、通常のニュースやメールのメッセージについては確実に動
作する安全なものにはなっている. 

良く使う引数は以下の通りです.

["-j"]
junet コードを出力する. (デフォルト)
["-e"]
EUC コードを出力する.
["-s"]
Shift_JIS コードを出力する.
["-w"]
Unicode を出力する.
["-J"]
入力として junet コードを仮定する.
["-E"]
入力として EUC コードを仮定する.
["-S"]
入力として Shift_JIS コードを仮定する.
["-W"]
入力として Unicode を仮定する.
["-g"]
自動判別の結果を出力する.
["--overwrite もしくは --in-place"]
変換結果で元のファイルを上書きする.

例えば, 文字コードを自動判別させる場合には以下の様にコマンドを実行します.

$ nkf -g [判別させるテキストファイル]

次の様にコマンドを実行すると, 変換した結果を端末(標準出力)へ表示します. 以下の例では junet コードのファイルを EUC-JP へ変換し, 端末へ表示します.

$ nkf -Je [変換するテキストファイル]

変換結果を保存するには以下の二通りの方法があります.

リダイレクトを用いる場合には

$ nkf -Je [変換するテキストファイル] > [変換後ファイル名]

上書き保存する場合する場合には

$ nkf -Je  --overwrite [変換するテキストファイル]

となります. それでは最後の実習です.

["実習その6:先程ダウンロードしたファイルの文字コードを判別し, 結果が正しくなるかを確認して下さい. また, text-eucjp.txt の中身を Shift_JIS に, text-utf8.txt の中身を junet コードに, text-sjis.txt の中身を UTF-8 に変換して下さい. 変換方法はお任せします."]

以上で実習は終了です. お疲れ様でした.

前項: [ 公開鍵認証を使ったssh接続実習 ]

[ 2010 スケジュール表・各回資料(06/18) ]


*1 "lv" などの高機能なプログラムを使用すると 端末の環境変数やファイルの文字コードを自動判別して, 適切に処理してくれたりします. ですが自動判別に失敗した場合や, これらの高機能ページャを使用できない場合には やはり設定が必要です.
*2こう書くと「LANGUAGE を設定しておけば良いんだ」と考える人もいるかもしれませんが, LANGAUGE は GNU gettext を使用する一部のプログラムでしか使用されません
*3 かつて通産省肝いりで進められていたΣプロジェクトで, EUC-JP を UJIS と読んでいた事に起因する呼び名.