りんけーじ - 開発資料 - サーバ - Perl で UTF-8 文字列をバイト数でカットする



この文書について

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 として正常に終了していない場合には、その部分がカットされます。


更新履歴

2007/09/15
作成

コメント(0) トラックバック(0)

コメントフォーム

(必須)

<Trackback URI> http://linkage.white-void.net/cgi/tb.cgi/development/server/perl-utf8-strcut