Shift_JIS でもエラーにならない Perl 正規表現

Shift_JIS 正規表現の解説

正規表現に日本語を含めたい場合があります。
例えば、ユーザの入力が準備したキーワードリストに一致するか、などをチェックしたい場合などです。

この場合、プログラムコード(チェックする文字列表現)が EUC-JP で記載されていれば問題無いのですが、Shift_JIS の場合、文字コードの中にPerlの特殊文字や正規表現上の特殊文字が含まれる場合があり、うまくマッチしなかったり、場合によってはエラーになります。

正規表現の問題の例

プログラムが EUC-JP で記載されている場合、以下のコードはすべて期待通り動作します。

#プログラムが EUC-JP で記載されていれば、期待通り動作

$teststr = '電話';
print "$teststr MATCHED\n" if $teststr =~ /$teststr/;

$teststr = '申請書';
print "$teststr MATCHED\n" if $teststr =~ /$teststr/;

$teststr = 'メール';
print "$teststr MATCHED\n" if $teststr =~ /$teststr/;

上記のコードを実行した場合の出力は以下の通りになります。

電話 MATCHED
申請書 MATCHED
メール MATCHED

では今度は、上記のプログラムを Shift_JISで保存するとどうなるでしょうか?
出力をフラッシュするようにしておけば、以下のような表示となります。

電話 MATCHED
Unmatched [ before HERE mark in regex m/メー << HERE ル/ at testcode.pl line xx.

この場合、「電話」は EUC-JP の場合と同じように期待通り動作しています。

「申請書」はエラーにはなりませんが、「申」(905c)には正規表現上の特殊文字「\」(5c)が含まれているため、うまくマッチしません。
「申請書」をそのまま正規表現に使用すると 5c の部分が正規表現上の特殊文字(次の1文字の特殊性を無くす。)と解釈され、「(申の前半1バイト)請書」という文字をマッチさせようとしているように解釈されます。

「メール」は正規表現自体がエラーになってしまいます。これは、「ー」(815b)に正規表現上文字クラスを記載する特殊文字「 [ 」(5b)が含まれているため、正規表現が完結していない、とみなされてしまうためです。
「 Unmatched [  云々」としかられるのはこのためです。

CGIなどでこの表現を使うと、マッチしようとする文字列によって Internal Server Error になったりならなかったり、という現象が発生することになります。