すなわち「全角」を2文字「半角」を1文字分として数えたい、というケース。
(画像に埋め込むフォントは等幅を想定してます)
文字幅を計算する必要がある、ということはlengthなんかの文字数でのカウントはできない。
そこでいろいろ考えたりググったりしてみたところ、tokuhiromさんのblogでUnicode::EastAsianWidthの話を見つけた。
このモジュールはUnicodeコンソーシアムの定めるEastAsianWidthに基づき「全角に該当する文字」「半角に該当する文字」etcにあたるUnicode属性を提供するもので、useすると下記のようなUnicode属性が正規表現で使えるようになる。
/(?:(\p{InFullwidth}+)|(\p{InHalfwidth}+))/g
これを使うと「文字幅」をカウントできるようになるのです。
下記はそのプログラムの一例
use strict;
use warnings;
use Unicode::EastAsianWidth;
use utf8;
sub visualLength {
my $text = shift or '';
my $length = 0;
while ($text =~ /(?:(\p{InFullwidth}+)|(\p{InHalfwidth}+))/g) {
# 全角に該当すれば2、そうでなければ1インクリメント
$length += ($1 ? length($1) * 2 : length($2));
}
return $length;
}
my $text1 = "あいうえお"; # 10
my $text2 = "hogehoge"; # 8
print visualLength($text1), "\n";
print visualLength($text2), "\n";
多少冗長なコードかも。
ちなみにその「EastAsianWidth」の定義ってどんなん?という疑問がわいた方はここを見ると全部のってます。
補足
Unicode関係で超参考になったページ
http://totonica.s41.xrea.com/doc/delphi_tiburon/doc_unicode/eastasianwidth.htm

1 コメント:
近くの方から突っ込みをいただいたので、use warnings;と、visualLengthの引数を受け取るところに「or ''」を追加しました。
コメントを投稿