日本語の問題
 一般的にWindowsやMacのパソコンでは日本語の文字コードにシフトJISが使われています。しかし、CGIプログラムをシフトJISで記述すると文字化けやエラーを起こす場合や正規表現が正常に実行されない場合があります。原因は、日本語が1文字2バイトのコードで表されますが、その2バイト目がPerlの特殊文字に重複したり正規表現にマッチしたりする為です。以下に問題点の内容と対策を示します。

文字化けの問題
日本語のシフトJISで2バイト目がPerlの特殊文字に重複すると文字化けが起きる場合があります。文字コードにEUCを使えば重複しないので文字化けは起こりません。

◆ 2バイト目が\の文字
 2バイト目がシフトJISで「5C」になる文字は「\」を表し、「\」はメタ文字に解釈される為、2バイト目は次の文字コードになります。従って、その該当文字及び次の文字が化けてしまいます。その為、特に文字列の最後に上記の文字を記述すると文法エラーを引き起こします。
    例 "ソフト"→ャtト  "表示"→侮ヲ   (「ソ」「表」の2バイト目が\)
2バイト目が「\」になる主な文字を下記に示します。
   ― ソ \ 表 予 能 申 十 構 貼 暴 欺 圭 噂 蚕 饅 箪 禄 兔 彌

対策を下記に示します。
 ・上記の文字の直後に「\」を付けます。これによってメタ文字に解釈される「\」を補います。
    例 "ソ\フト" "表\示" "予\定"
 ・シングルクォート文字列を使います。
    例 'ソフト' '表示' '予定'
  但し、文字列の最後に上記の文字を記述すると「\'」になる為、「'」が文字列に含まれてしまい文法エラーになります。
  その場合は「\」を付けます。
    例 '予定表\'

◆ 2バイト目が@の文字
 2バイト目が「@」になる文字は、その次の文字に配列変数で使われる文字又は数字があると配列に解釈されて文字化けが起きます。
    例 "方法A案"→方毎ト  (「法」の2バイト目が@)
2バイト目が「@」になる主な文字を下記に示します。
   ・全角スペース
   ・ァ 法 機 鼻 院 諭 繊 掘 察 宗 邸 如 后 魁 拭 叩 蓮 廖

対策はシングルクォート文字列を使います。
    例 '方法A案'  '方法',"$a案"


正規表現での問題
 正規表現に日本語を使う場合は下記のような問題があります。

◆ 2バイト目に正規表現で使う文字がある場合
 日本語の2バイト目に正規表現で使う文字があると正しく実行されなかったり、文法エラーが起きたりします。特にフォーム入力のデータを正規表現に使う場合は、入力データによってエラーが起きたり起きなかったりするので注意が必要です。正規表現で使う文字 ^ \ $ * + ? . | [ ] { } ( )
    例 if ($data =~ /充分/) { }     文法エラーになります。「充」の2バイト目が [ であり ] がない為です。
       $a='充'; if ($data =~ /$a/) { }  この文を実行した時にエラーになります。

対策はメタ文字\Q\Eを使います。これは\Qから\Eまでの非英数文字の前に\を付けます。
    例 if ($data =~ /\Q充分\E/) { }
       if ($data =~ /\Q$a\E/) { }

◆ 1バイトずれで誤ってマッチしてしまう場合
 2バイト目又はそれ以降のバイトずれした文字は誤ってマッチしてしまう場合があります。
    例 $data = '充分';
       if ($data =~ /\Q[\E/) {print '一致';}  「充分」は [ にマッチしてしまいます

 文字コードがEUCでもバイトずれによってマッチしてしまう場合があります。
 対策は1文字毎のバイト長を認識させればいいですが複雑になるので割愛します。
 正規表現で記述する文字長が大きければ誤ってマッチする可能性は低くなります。
■プログラム (sample29.cgi)
print "ソフト、Z[\]、表示、予定、能力、申し込み、十分、構造<br>";
print "ソ\フト、Z[\\]、表\示、予\定、能\力、申\し込み、十\分、構\造<br>";
print 'ソフト、Z[\]、表示、予定、能力、申し込み、十分、構造<br>';
print '予定表\';
print "<br>―\ソ\\\表\予\能\申\十\構\貼\暴\欺\圭\噂\蚕\饅\箪\禄\兔\彌\<br><br>";

print "方法案  方法A案";
print '  方法A案<br>';
$a = 'A';
print "方法$a案";
print '  方法',"$a案<br><br>";

$data = '充分';
if ($data =~ /\Q充分\E/) {print '一致 ';} else {print '不一致 ';}
$a = '充';
if ($data =~ /\Q$a\E/) {print '一致 ';} else {print '不一致 ';}
if ($data =~ /\Q[\E/) {print '一致 ';} else {print '不一致 ';}
■実行結果
ャtト、Z[]、侮ヲ、嵐閨A迫ヘ、垂オ込み、助ェ、国「
ソフト、Z[\]、表示、予定、能力、申し込み、十分、構造
ソフト、Z[\]、表示、予定、能力、申し込み、十分、構造
予定表
―ソ\表予能申十構貼暴欺圭噂蚕饅箪禄兔彌

方法案  方毎ト  方法A案
方毎ト  方法A案

一致 一致 一致


HOME Copyright (C) CGI-design All Rights Reserved.