日本語の取り扱いについて


 ここ BIGLOBE と CGI であそぼう! は、基本的に Shift-JIS(MS-Kanji) で記述しています。 HTML や CGI などのプログラムの中もすべて Shift-JIS で記述しています。 どうも、EUC で書いた方がよいという方が多いようなのですが、 変換すると手数が増えるもんで(^^;;;
 Shift-JIS だと、いろいろと問題が起こります(^^;;;


Perl と Shift-JIS の組み合わせで文字化けする例

Perl と Shift-JIS の組み合わせで、 プログラムが期待した動作をせずに、日本語が化けてしまうことがあります。
Shift-JIS の漢字の 2byte 目が \ (0x5C) にあたる場合があるためです。 日本語を含む文字列は、 " (ダブルクォート) で囲まず、 ' (シングルクォート)で囲むなどの配慮が必要になります。
シングルクォートで囲んだ場合にも、最後の文字の 2byte 目が \ (0x5C) にあたるとエラーになります。 シングルクォートの中でも、\' と \\ の2つのエスケープシーケンスは有効なので、 クォートが閉じなくなってしまうためです。

Perl と Shift-JIS での文字化けの例  中身です。

EUC では、この問題はおこりません。

2byte 目が 0x5C の文字
―ソЫ\噂浬欺圭構蚕十申曾箪貼能表暴予禄兔喀媾彌拿杤歃濬畚秉綵臀藹觸軆鐔饅鷭\\
さらに、マッチなどの正規表現との関係は、もっと問題が起きます(^^;;;
この問題については、そのうち...

gcc と Shift-JIS の組み合わせで文字化けする例

Shift-JIS の漢字の 2byte 目が \ (\x5C) にあたる場合には、 gcc ではコンパイルで下記のような警告がでたり、日本語が化けてしまうことがあります。
gcc_sjis.c: In function `main':
gcc_sjis.c:5: warning: unknown escape sequence: `\' followed by char code 0x8e
gcc_sjis.c:20: warning: unknown escape sequence: `\' followed by char code 0x8e
これを回避する方法は、perl より、やっかいだなぁ(^^;;;
\ をいれたり、16進で書いたりすることなどの配慮が必要になります。

gcc と Shift-JIS での文字化けの例  ソースプログラムです。

\x81\x5c ―
\x83\x5c ソ
\x84\x5c Ы
\x87\x5c \
\x89\x5c 噂
\x8a\x5c 浬
\x8b\x5c 欺
\x8c\x5c 圭
\x8d\x5c 構
\x8e\x5c 蚕
\x8f\x5c 十
\x90\x5c 申
\x91\x5c 曾
\x92\x5c 箪
\x93\x5c 貼
\x94\x5c 能
\x95\x5c 表
\x96\x5c 暴
\x97\x5c 予
\x98\x5c 禄
\x99\x5c 兔
\x9a\x5c 喀
\x9b\x5c 媾
\x9c\x5c 彌
\x9d\x5c 拿
\x9e\x5c 杤
\x9f\x5c 歃
\xe0\x5c 濬
\xe1\x5c 畚
\xe2\x5c 秉
\xe3\x5c 綵
\xe4\x5c 臀
\xe5\x5c 藹
\xe6\x5c 觸
\xe7\x5c 軆
\xe8\x5c 鐔
\xe9\x5c 饅
\xea\x5c 鷭
\xed\x5c \
\xee\x5c \
変換フィルターか、専用プリプロセッサなんていうのを、 どこかの誰かが作っているに違いない(^^;;;

3つの日本語コード

 パソコン系は Mac も Win も Shift-JIS ですが、 環境によって、 Shift-JIS、JIS、EUC の3つのコード系があります。
ユーザーからの入力と CGI 内部などからの文字列とのコード系が違うと、 混在してしまうわけです。 そこで、入力された文字列を変換する必要があるわけです。

 掲示板などのユーザーからの入力があるフォームの処理が問題になります。 一つのページ内に複数のコード系が混在していると、ブラウザで見る時に文字化けします。 ユーザーの入力をチェックして、変換してコード系を統一することが必要になるわけです。

 HTML や CGI などのプログラムの中もすべて Shift-JIS で記述してあって、 入力をチェックしないと、Shift-JIS 以外のコード系で入力されたときには、 文字化けする事になるはずです。

 また、STEP 4 の例では、sendmail から発信されるメールが、 広い?インターネットのどこかで文字化けしましたので、 これを JIS コードに変換することで対応しました。

 perl で、日本語コードの変換をするライブラリとして有名なのが jcode.pl や Kconv です。 UNIX のフィルタとして日本語コードの変換をするのが nkf コマンドです。

3つの日本語コードの例

Shift-JIS  中身です。
JIS  中身です。
EUC  中身です。

この3つが混在してファイルを表示してみます。
むちゃくちゃになる混在の例  中身です。
ユーザーからの入力と CGI 内部などからの文字列とのコード系が違うと、 混在して文字化けしてしまいます。 そこで、入力された文字列を変換する必要があるわけです。


参考
Perlで日本語を扱う際の留意点 ( Perl初心者の部屋 )
The Web Kanzaki 日本語と文字コード
日本語 EUC ・シフト JIS 間コード変換仕様とコード系実態調査 (OSF/JVC)
各社の文字コード調査結果 (OSF/JVC)


jcode.pl による入力の変換

 jcode.pl をつかって入力を Shift-JIS に変換すると、うまくいくはずです。

jcode.pl の所在
www2d.biglobe.ne.jp には、jcode.pl がインストール済でした。
/usr/local/lib/perl5/jcode.pl (v 1.9)
最新の jcode.pl の入手元は こちら です。jcode.pl,v-2.6 98/02/20 現在

 jcode.pl は入力のコード系を自動判定する機能がありますが、 半角のカナには対応していません。


参考
jcode.pl の私的な解説書
JIS X 0201 片仮名

半角カナへの対応

 半角カナの取り扱いは、けっこう問題が多いようです。

 EUC は、JIS X0208 に基づいていて、JIS X0201 (半角カナ文字)の取り扱いは、 ベンダーによる拡張という取り扱いになっているようです。 前半の 1byte を 0x8E にしているのですが、 これが、ぜーんぶ Shift-JIS の領域と重なります、 JIS の半角カナは、EUC では全角の日本語の領域とかさなります。

 半角カナを jcode.pl,v 2.6 に入力すると、 EUC の半角カナは Shift-JIS と判定し、 JIS ( = Shift-JIS ) の半角カナは EUC と判定するようです。

 jcode.pl は改変版も自由に公表してもいいらしいので、 半角カナの取り扱いをめざして、ささやかに改変してみました。

jcode'getcode の改変版 getcode.pl です。
この改変版ルーチンをオリジナルの jcode.pl とともに使用する事にしてみました。

 まず、判定する文字数が多いほど、正答できる確率が高くなるので、 いったん全部よみこんで、すべての入力をつなげてコードを判定することにします。

 半角カナを考慮すると、EUC と Shift-JIS の判別できない場合がでてきます。 決められない場合に、正解できる確率が高くなるように、 CGI での事情を考慮に入れて、もうちょっと、四苦八苦することにします。

 代表的なブラウザは読んでるページのコード系にあわせて、 同じコード系で送信してくれるようです。

 読んでるページのコード系にあわせずに、 送信を JIS で送信する場合もあるようです。 コード系が正しく判定されることを期待しているのではないか?と思います。

 また、すべて、EUC で送ってくる環境もあるようです。

 getcode.pl では決められなかった時は、 CGI ならではの誤変換対策として、 ブラウザが設定する環境変数 HTTP_USER_AGENT を参照して、 'Mac' とか 'Win' という文字列が含まれれば、Shift-JIS とする事にします。

 'Mac' とか 'Win' という文字列が含まれないときは、EUC とします。 Shift-JIS が入力された場合に正しく判定できる確率が高いからです。

ということで、こんな感じになるかな?
        local($jstr)=join(' ', $title, $name, $comment);
        local($match, $icode) = &getcode'getcode(*jstr);
        unless ($icode) {
            if ( $ENV{'HTTP_USER_AGENT'}=~ /Mac|Win/) {
                $icode = 'sjis';
            } else {
                $icode = 'euc';
            }
        }
        if ($icode ne 'sjis') {
            &jcode'convert(*title, 'sjis', $icode );
            &jcode'convert(*name, 'sjis', $icode );
            &jcode'convert(*comment, 'sjis', $icode );
        }
補記
Netscape では、 [ja_euc]と書いてくれてる場合もあるのですが、 ブラウザは読んでるページのコード系にあわせて、Shift-JIS を送出してくれるようです。 この点は、利用しない事にしました。

誤変換への対策のテストに、ご協力ください。

 ということで、サンプルが足りないしテストする機材もないので、 サンプル収集に、ご協力ください。
 特設掲示板 テストを終了しました。


nkf

 nkf は、UNIX のフィルタとして働き、日本語コードの変換を行います。
 nkf は、/usr/local/bin/nkf にあります

 STEP 4 メールうけたまわりフォームを作ろう! では、 オプションなしで nkf を起動して、入力から、JIS コードに変換して出力していることになります。

 nkf -v で下記のような説明が出てきます。
USAGE:  nkf [flags] [file]
Flags:
b       Output is bufferred (DEFAULT)
u       Output is unbufferred
t       no operation
j       Outout code is JIS 7 bit (DEFAULT)
s       Output code is Shift JIS
e       Output code is AT&T JIS (EUC)
i_      Output sequence to designate JIS-kanji (DEFAULT B)
o_      Output sequence to designate ASCII (DEFAULT B)
r       {de/en}crypt ROT13/47
v       Show this usage
m       MIME ISO-2022-JP decode. ISO8859-1 needs -l
l       ISO8859-1 (Latin-1) support
f       Folding: -f60 or -f 
Z       Convert X0208 alphabet to ASCII
X,x     Assume X0201 kana in MS-Kanji, -x preserves X0201
J       Assume JIS 7 bit input
E       Assume AT&T JIS (EUC) input
S       Assume MS-Kanji input
B       Assume Broken JIS; ESC missing input
Network vKanji Filter Version 1.5 (1/9503/Shinji Kono)
Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa)
入力のコード系は nkf が判定して Shift-JIS へ変換する例。
JIS コードを Shift-JIS にしてみる。  中身です。
EUC コードを Shift-JIS にしてみる。  中身です。
BIGLOBE 以外で nkf がインストールされていないサーバーのために nkf をインストールしてみました。
また、nkf がコンパイルできないサーバーのために Perl と jcode.pl で nkf もどきも作ってみました。
RIMNET 別館にてご覧ください。


Kconv について

Perl5 用の日本語変換ルーチンです。
kconv, tosjis, tojis, toeuc の4つのサブルーチンがあります。
gcc が動作していれば、自分でもインストールできそうなのです。 Kconv をインストールしてみようと思っているのですが・・・


ホームページへ