Perlで文字列長(バイト数)を求めるにはパート2
約2年前の2007/12/3に以下の記事を書きました。
しかし、length関数は、utf8 pragmaするとバイト数でなく、文字数を返すようになるのです。
で、バイト数を求めるにはと…ググると以下のfbisさんのページに遭遇しました!
このページでは、学ぶべきことが沢山あったのでメモしときます。
◆引用ソース(多少アレンジさせていただきました)
use strict; use warnings; # ポイント1 use utf8; my $utf8_str = 'シンガー小池啓仁'; my $bytes; # ポイント2 $bytes = length $utf8_str; print $bytes, "\n"; # ポイント3 #require bytes; use bytes(); # ポイント4 $bytes = bytes::length $utf8_str; print $bytes, "\n"; # ポイント5 $bytes = length unpack('a*',$utf8_str); print $bytes, "\n"; # ポイント6 { use bytes; $bytes = length $utf8_str; print $bytes, "\n"; } # ポイント7 use Encode; Encode::_utf8_off($utf8_str); $bytes = length $utf8_str; print $bytes, "\n"; Encode::_utf8_on($utf8_str);http://d.hatena.ne.jp/fbis/20080126/1201320719
◆実行結果
C:\perltest>length.pl 8 24 24 24 24
『シンガー小池啓仁』の文字列数は8で、バイト数は24になります。
UTF-8では、漢字1文字を3バイトでエンコーディングします。
◆ポイント1
use utf8;
utf8 pragmaの宣言です。
これは、大雑把にいってしまうと、文字列をちゃんと文字列として扱います。
utf8 pragma以前は、文字列をバイト列として扱っていた為に、文字化け等の問題がありました。
今のPerlで漢字を扱う場合は、utf8 pragmaを宣言し、ソースの文字コードをUTF-8にするのが推奨です。
◆ポイント2
$bytes = length $utf8_str;
これは、標準の組み込み関数(メインモジュール)のlengthを使用していますが、utf8 pragmaの時は、バイト数でなく文字数を返します。
◆ポイント3
#require bytes; use bytes();
require bytesとuse bytes()は、ほぼイコールです。
require bytesは、実行時にbytesモジュールを読み込みます。
use bytes()は、コンパイル時にbytesモジュールを読み込み、そして、空リスト()を指定しているので、このモジュールからのインポートは無しです。
もし、空リストを指定しないと(use bytes;)bytesモジュールのlength関数がインポートされて、メインモジュールのlengthがオーバーライドされてしまいます。
◆ポイント4
$bytes = bytes::length $utf8_str;
bytesモジュールのlengthを使用しています。これは、文字数でなくバイト数を返します。
◆ポイント5
$bytes = length unpack('a*',$utf8_str);
unpackで文字列$utf8_strをバイト列に変換して、メインモジュール(組み込み関数)のlength でそのバイト数を返します。
◆ポイント6
{ use bytes; $bytes = length $utf8_str; print $bytes, "\n"; }
中カッコの中がスコープになり、この中だけbytesモジュールのlength関数が適用され、バイト数が取得できます。
◆ポイント7
use Encode; Encode::_utf8_off($utf8_str); $bytes = length $utf8_str; print $bytes, "\n"; Encode::_utf8_on($utf8_str);
文字列のUTF8フラグをオフにするとバイト列になり、これをメインモジュールのlengthでバイト数を取得できます。
その後、UTF8フラグをオンに戻します。