- PR -

Perl アルファベット小文字→大文字変換について

1
投稿者投稿内容
Jumpin'' Jack Flash
大ベテラン
会議室デビュー日: 2006/01/24
投稿数: 198
投稿日時: 2007-03-22 13:03
Perlの質問は、こちらでよろしかったでしょうか。
文字列のアルファベット小文字→大文字変換を行っています。

$str =~ tr/a-z/A-Z/;

これだと、文字列に2バイトコードが含まれる場合、文字化けを起こします。
解決方法をググったところ、URLエンコードを行ってから変換し、URLでコードする
という解決方法が一般的なようでした。

$str =~ s/([^\w ])/'%' . unpack('H2', $1)/eg;
$str =~ tr/ /+/;
$str =~ tr/a-z/A-Z/;
$str =~ tr/+/ /;
$str =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;

しかし、これでも文字化けします。

元の文字列:aBcエービーシー
エンコード:aBc%83G%81%5b%83r%81%5b%83V%81%5b
小→大変換:ABC%83G%81%5B%83R%81%5B%83V%81%5B
 デコード:ABCエーコーシー

unpack関数('H2')が2バイトコードの1バイト目しか16進にエンコードしない場合があるようです。
2バイト目が0-9a-zA-Zで表現できる場合は2バイト目をエンコードしないようです。
ですから、大文字に変換する際、2バイトコードの2バイト目を変換してしまい、文字化けになるようです。

元の文字列:aBcエービーシー
エンコード:aBc%83%47%81%5b%83%72%81%5b%83%56%81%5b

このように、2バイトコードの2バイト目もエンコードしてくれれば、文字化けはしないはずです。
その方法を教えてください。正規表現でできればスマートかなと思っています。

よろしくお願いいたします。


[ メッセージ編集済み 編集者: Jumpin' Jack Flash 編集日時 2007-03-22 13:05 ]
たお
ベテラン
会議室デビュー日: 2006/10/27
投稿数: 90
投稿日時: 2007-03-22 13:35
文字化けしなかったです。
perlはv5.8.4です。

コード

$string="aBcエービーシー";
print "$string \n";
$string =~ tr/a-z/A-Z/;
print "$string \n";

結果

aBcエービーシー
ABCエービーシー

jcodeのモジュールなどを使用するのはどうでしょうか?
&jcode::tr(\$string, 'a-z', 'A-Z');
とか。
Ay
常連さん
会議室デビュー日: 2006/10/29
投稿数: 45
投稿日時: 2007-03-22 13:41
こんにちは

uc という組み込み関数がありますよ。


とおもったら、shift_jis ですかね。
euc で文字列を与えたら大丈夫だとおもいます。

引用:

Jumpin' Jack Flashさんの書き込み (2007-03-22 13:03) より:

unpack関数('H2')が2バイトコードの1バイト目しか16進にエンコードしない場合があるようです。
2バイト目が0-9a-zA-Zで表現できる場合は2バイト目をエンコードしないようです。
ですから、大文字に変換する際、2バイトコードの2バイト目を変換してしまい、文字化けになるようです。



「2バイトコードだけ変換」じゃなくて「全部変換」すれば、
URLデコード時に大文字小文字が関係なくなるので大丈夫なのでは?

試してないけど
コード:
$str =~ s/(.)/'%' . unpack('H2', $1)/eg;

Jumpin'' Jack Flash
大ベテラン
会議室デビュー日: 2006/01/24
投稿数: 198
投稿日時: 2007-03-22 15:06
こちらの環境は、Windowsの
perl, version 5.005_03 built for MSWin32-x86-object
でした。
ucを使っても結果は同じでした。

引用:

jcodeのモジュールなどを使用するのはどうでしょうか?
&jcode::tr($string, 'a-z', 'A-Z');
とか。



この方法でできましたが、できればこれだけのために
外部モジュールは使いたくないものです。

引用:

とおもったら、shift_jis ですかね。
euc で文字列を与えたら大丈夫だとおもいます。



eucに変換するのにjcodeなど使うと思われるので、今のところ
&jcode::tr($string, 'a-z', 'A-Z');
この方法で応急処置しています。

引用:

「2バイトコードだけ変換」じゃなくて「全部変換」すれば、
URLデコード時に大文字小文字が関係なくなるので大丈夫なのでは?



これだと、小文字→大文字変換ができなくなります。

引用:

元の文字列:aBcエービーシー
エンコード:aBc%83%47%81%5b%83%72%81%5b%83%56%81%5b


このようにエンコードする方法があればバターだと思いますが、
無理ですか?
たお
ベテラン
会議室デビュー日: 2006/10/27
投稿数: 90
投稿日時: 2007-03-22 22:36
環境は、v5.8.8 built for MSWin32-x86-multi-threadです。
前回のレスとまったく同じ方法で、文字ばけしませんでした。

一応報告です。
perlのバージョンを上げるってのは、マーガリンですかね?
ちいにぃ
大ベテラン
会議室デビュー日: 2002/05/28
投稿数: 244
投稿日時: 2007-03-23 00:59
Perlの文字コードの扱いは 5.005 → 5.6 → 5.8 の間で結構違いますから、
面倒だったりします。(なので、私は 5.005 と 5.6 のことは忘れることにしました)

ちなみに 5.8 ではUnicodeを使うようになり、標準で添付されるEncodeモジュールで扱えるようになりました。
- Perl 5.8.x Unicode関連
- Perl5.8.0JP
- Perl 5.8の新機能
Jumpin'' Jack Flash
大ベテラン
会議室デビュー日: 2006/01/24
投稿数: 198
投稿日時: 2007-03-23 11:05
皆様、コメントありがとうございます。

引用:

Perlの文字コードの扱いは 5.005 → 5.6 → 5.8 の間で結構違いますから、
面倒だったりします。(なので、私は 5.005 と 5.6 のことは忘れることにしました)



私も個人的にはそう思うのですが、今回、業務システムなので、
おいそれとバージョンを上げられません。
「結構違う」とのことですので、他への影響を考えるとなおさらです。

バターもマーガリンも使えず、jcodeのおいしさを知りました。
今回は、jcode.plで対応したいと思います。

ありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)