- 締切済み
PERLのSHIFT_JISの振る舞いについて
PERLでプログラムを作る時、SHIFT-JIS形式で長音符(ー)があると、エスケイプしてもエラーが出てしまい困っています。 また、ホームページそのものがSHIFT_JIS形式のため、UTF-8など他の形式を使うと煩雑になるため避けたいと思っています。 エスケイプさせるなど簡単な方法は無いものでしょうか? また、こちらはご存じでしたら教えていただきたいのですが、「¥」マークでエスケイプしてもうまくいかない文字には他にどの様なものがありますでしょうか? ---test.pl---SHIFT_JIS形式---- $| = 1; $test = "\テ\ス\タ\ー"; $test =~ s/\テ\ス\タ\ー/tester/; print $test; エラーを見ると、 Unmatched [ in regex; marked by <-- HERE in m/\テ\ス\タ\ー <-- HERE / at test.pl line 3. とでます。
- みんなの回答 (4)
- 専門家の回答
みんなの回答
- kumoz
- ベストアンサー率64% (120/185)
変数の代入文に直接日本語文字列を書かずに、外から読み込むようにすればかなりのエラーは防げると思います。 $pattern = <DATA>; chomp $pattern; $string = <DATA>; $string =~ s/\Q$pattern/tester/g; print $string; __DATA__ テスター テスターを変換して表示します
- kmee
- ベストアンサー率55% (1857/3366)
いわゆる「Shift_JISのダメ文字」というのは、「全角文字」を「1文字」ではなかく「2バイト」と判定してしまう処理系で、その2バイト目が特殊な意味を持つ記号と一致してしまうめに発生するものです。 テスター というShift_JISの文字列は AeBXC^D[ という文字列とほぼ同じ扱いになります。A,B,C,Dは1バイト目で実際は128以上の文字コードを持つものです。 通常、特殊な文字の前に\を付けて、特殊な意味を取り消す、と本には出ています。 それで\テ\ス\タ\ー としたのでしょうが、上の例に従えば \Ae\BX\C^\D[ とA,B.C.Dをエスケープしているだけで、2バイト目の^,[はまったくエスケープされていません。 よくある ソ\ は最後が\だから有効な技です。 正直、簡単じゃないです。 ・ーのあと[を無効にするために[] を付けてー[]とする ・特殊文字を無効にする\Q~\Eで囲む などがありますが。 内部ではutf-8、出力をShift_JISというのが無難かもしれません
- shincha119
- ベストアンサー率42% (95/226)
No1です。 例の場合テスターの「ー」の後の文字が「¥」ではなく「/」なのでエラーになってるのではないかなと。 つまり「ー」や「表」の2バイト文字はコードにすると「5C」が2バイト目になり、この5Cを1文字に直すと「¥」になります。 「ー」の場合だとプログラム内部では「815C」と認識され、5Cの部分が「¥」と解釈されてしまうため、結果として「(81の文字:?)+(5Cの文字:¥) = 文字化けした変な文字ということになるのです。 index()を用いてと書いたのは例えば「テスター」の場合4文字目に「ー」が来るので、特定の文字が見つかったら「¥」を付加するような文字列にすればいいのでは?と思ったわけですが、ちょっと面倒ですね。 使ったことはないので何とも言えないですが、encode関数で正規表現に渡す前に変換すればうまくいくかもしれません。 ---test.pl---SHIFT_JIS形式---- $| = 1; $test = "\テ\ス\タ\ー"; $test =~ s/\テ\ス\タ\ー/tester/; # 追加 # 文字列をUTF-8に変換 $str = encode('UTF-8', $test); # 追加 # 変更 #print $test; print $str; # 変更 文字化けを起こす文字コードについては以下を参照してください。 http://www.geocities.co.jp/SiliconValley-Sunnyvale/6128/perl/bake.html
- shincha119
- ベストアンサー率42% (95/226)
Shift-JISを正規表現で使うのは文字コードの問題で結構面倒ですので、index等で特定文字の後ろに\を付けてから正規表現に渡すなどの工夫が必要です。 参考になると思うので一読してみてください。 http://homepage1.nifty.com/nomenclator/perl/shiftjis.htm
お礼
回答いただきありがとうございます。 ちょっと、説明文が理解できない(perl初心者)なのですが、 >index等で特定文字の後ろに\を付けてから正規表現に渡すなどの工夫が必要です はどういう意味でしょうか? 例では、念のため全てに¥マークを付けています。 これでは不十分と言うことでしょうか? 可能であればもう少し、分かり易く説明いただければ幸いです。 また、これは、今まで使ったことがなく、振る舞いがよく分かりませんので使うのは怖いのですが、紹介いただいたHPにVer5.8.Xより便利になったという記載がありましたので、ググってみたところ ---test.pl---SHIFT_JIS形式---- use encoding "shiftjis"; binmode STDERR, ":encoding(shiftjis)"; $| = 1; $test = "\テ\ス\タ\ー"; $test =~ s/\テ\ス\タ\ー/tester/; print $test; ---------------------------- を使うと上手に処理できるようでした。 参考 http://www.fl.reitaku-u.ac.jp/~schiba/perl/perlEncoding.html