この文書について
Trackback などの入力を処理するにあたって、長さを制限したいときなどには substr を使います。
しかし、use utf8 な状態では「文字数」しか制御できませんし、そうでない場合はバイト数を制御してしまい、UTF-8 として正しくないものが出来上がってしまいます。
ここで紹介するのは、UTF-8 の文字列を最大~バイト切り出す方法です。
なお、以下のものは UTF-8 専用です。Shift-JIS や EUC-JP など他のエンコーディングについて使用したい場合、また、ちゃんと Perl 純正のモジュールを使用しての実装は、北村曉氏の「Perl内部文字列をバイト数でカットしてみる」を参照ください。Perl の utf8 を使用した、正しい実装が紹介されています。
(というか、同じアプローチでもっときれいなのが「UTF-8文字列をバイト数でカットした時の末尾の処理」にあります)
実装
前提として、use utf8 されていないことが必要です。そうでないなら、関数の頭としっぽに utf8::decode と utf8::encode を追加してください。
sub strcutbytes_utf8 {
my ($src, $maxlen) = @_;
my $srclen = length($src);
my $srcpos = 0;
while($srcpos < $srclen) {
my $character = substr($src, $srcpos, 1);
my $value = ord($character);
if($value < 0x80) { # ASCII characters
$srcpos ++;
next;
}
my $width = 6;
$width = 5 if($value < 0xFC);
$width = 4 if($value < 0xF8);
$width = 3 if($value < 0xF0);
$width = 2 if($value < 0xE0);
my $nextpos = $srcpos + $width;
last if($nextpos > $maxlen);
last if($nextpos > $srclen); # sequence is incomplete
$srcpos = $nextpos;
}
return substr($src, 0, $srcpos);
}
オマケとして、文字列が UTF-8 として正常に終了していない場合には、その部分がカットされます。
<Trackback URI> http://linkage.white-void.net/cgi/tb.cgi/development/server/perl-utf8-strcut
コメントフォーム