CGI-BBS > CGI > Perl > 離ればなれになった全角文字の1バイト目と2バイト目…


カレッヂ
カレッヂ


質問者 だいだ  投稿日 1/24(水) 18:42:57
部分文字列の切り出しで、全角文字の1バイト目と2バイト目がバラバラになったかどうかを判定しようと思っています。
例えば、掲示板などに書き込まれたメッセージから、substr()で一部を切り出し、この切り出した文字の先頭の1バイト目が、全角文字の2バイト目か? あるいは、切り出した文字列の最後の1バイトが、全角文字の1バイト目か? という判定です。
いまのところ、Shift-JIS で判定しようと思っていますが、他の文字コードならうまくいくとかいう情報でも構いません。
よろしくお願いします。
回答者 さくら  [削除]  投稿日 2/18(日) 01:22:43
質問から、だいぶ時間が経っていますが、解答者が無いので、一応解答します。
すでに解決済みなら、良いのですが、まだなら参考にして下さい。
ただ、日本語処理についてそれほど詳しくありませんので、ご了承下さい。

まず、文字コードについて(16進表記で書きます)
jis
1バイト目  0x21-0x7E
2バイト目  0x21-0x7E
s-jis
1バイト目  0x81-0x9F 及び 0xE0-0xEF
2バイト目  0x40-0x7E 及び 0x80-0xFC
euc
1バイト目  0xA1-0xFE
2バイト目  0xA1-0xFE
----------------------
つまり、どの文字コードを使っても、1バイト目と2バイト目は重なるので、文字コードで判定する事はできない事になります。

取り出した、文字列にASCIIを含んでいれば、可能性は有ります。
例えば、jis の場合、1バイト目がASCIIコードと重なる為、エスケープシーケンスを使って、
ここから、ASCII ここから JIS 等のように認識していますので、
このエスケープシーケンスに正確にマッチできれば、JIS文字の部分を取りだし、バイト数によって、一バイト目からか2バイト目からか判定できるでしょう、但し、1バイト文字である半角カナが入っていたら、ダメです。

このような感じなので、substrを使って任意の文字列を切り出すのは、やめたほうが良いのではないでしょうか。

掲示板などのメッセージでは、日本語もASCIIも混じっている事が有りますので、
1バイト目と2バイト目は切り離さずに取り出す方法を考えたほうが良いのではないでしょうか。

例えば、EUC は ASCII とコードが重ならないので、混在していても一文字を一文字として
マッチできます。
簡単な正規表現で書くと
/[\xA1-\xFE]{2}/  #これはEUCコードの一文字にマッチ
/[\x00-\x7F]/     #これはASCIIコードの一文字にマッチ

/\x8E[\xA1-\xFE]/  #これはEUCコードの1バイトの半角カナにマッチ
/\x8F[\xA1-\xFE]{2}/    #これは補助漢字にマッチ

これを、一つにまとめると

/[\x00-\x7F]|[\xA1-\xFE]{2}|\x8E[\xA1-\xFE]|\x8F[\xA1-\xFE]{2}/

これで、EUCとASCIIの混在している文字列でも正確に一文字づつ取り出せます。
又、()で囲んでグループ化すれば任意の文字数を取り出す事もできるでしょう。
但し、先頭からマッチさせなければいけないので、今回の質問の解答としてはかなり
消極的な方法と言えるかもしれません。

参考になればと思い、レスさせて頂きました。


質問者 だいだ  [削除]  投稿日 2/19(月) 08:41:14
回答、ありがとうございました。
EUC で判定すればいいんですね。なんとかなりそうです。

助かりました。

このページは終了したので返信(回答)は書きこめません

Web裏技