マルチバイト文字列の扱い「 心得 」
(
0x243) と (
0x244) では、Perl で日本語文字列 ( マルチバイト文字列 ) を扱う場合の基本を、次のように確認しました。
・プログラムファイルの文字コードは「 UTF-8 」とする。
・「 use utf8 」を利用して文字列リテラルを「 flagged utf8 」とする。
・外部から入力された文字列は デコード して「 flagged utf8 」とする。
・プログラムでは文字列を「 flagged utf8 」で処理する。
・外部へ出力する文字列は エンコード して任意の文字コードとする。
これらの基本を心得としてふまえて、関数「 substr 」で日本語文字列を操作してみます。
関数「 substr 」で日本語文字列を扱う
関数「 substr 」でマルチバイト文字列を利用するためのプログラムコードは次のものです。心得に忠実に基本的な処理を書いてみました。
# 文字列リテラルを flagged utf8 にする
use utf8;
# 文字列の エンコード / デコード を行うモジュール
use Encode;
# 文字列リテラル ( flagged utf8 ) をセット
my $string = "ハローワールド。ハローパール。";
# OFFSET 0 から 3 文字分を取り出す
my $substr = substr($string, 0, 3);
# 出力に備えて flagged utf8 を UTF-8 にエンコードする
my $enc_substr = encode('utf-8', $substr);
# UTF-8 で出力 ( ハロー )
print "$enc_substr\n";
これにより、print 文では文字列「 ハロー 」が出力されます。
13 行目で「 UTF-8 」へのエンコード処理を行わず、「 flagged utf8 」のまま文字列を出力すると、警告メッセージ「 Wide character in print at ... 」が出力されます。
関数「 index 」も加えて置換処理をする
関数「 substr 」の第 4 引数「 REPLACE 」を利用してマルチバイト文字列の置き換えを行います。 ここでは関数「 index 」も追加してみました。
use utf8;
use Encode;
my $string = "ハローワールド。ハローパール。";
# ワールド を マイフレンド に置換
substr($string, index($string, 'ワールド') , 4, 'マイフレンド');
my $enc_string = encode('utf-8', $string);
# ハローマイフレンド。ハローパール。
print "$enc_string\n";
プログラム内の処理は「 flagged utf8 」で行い、出力時に「 UTF-8 」へのエンコードを行っているので、7 行目の文字列置換も 12 行目の print 文での出力も問題なく完了します。
マルチバイト文字列の入力を処理する
外部からマルチバイト文字列の入力を受け付けて、処理してみます。
入力は、「 文字列 」,「 部分文字列 」,「 置換文字列 」を受け付けます。
外部から「 部分文字列 」を受け付ける場合は、関数「 substr 」の第 3 引数「 LENGTH 」の値が分からないので、関数「 length 」を利用して文字列の長さを取得するようにしています。
関数「 lnegth 」は (
0x53) 等で少し確認しています。
use utf8;
use Encode;
# 入力受付 ( 外部からは UTF-8 で入力される )
print "string: ";
chomp(my $string = <STDIN>);
print "substring: ";
chomp(my $substr = <STDIN>);
print "replace: ";
chomp(my $replace = <STDIN>);
# UTF-8 を flagged utf8 にデコード
my $dec_string = decode('utf-8', $string);
my $dec_substr = decode('utf-8', $substr);
my $dec_replace = decode('utf-8', $replace);
# flagge utf8 の文字列から長さを取得
my $length = length($dec_substr);
# 文字列はすべて flagged utf8
substr($dec_string, index($dec_string, $dec_substr ), $length, $dec_replace);
# 出力前に UTF-8 にエンコード
my $enc_string = encode('utf-8', $dec_string);
print "$enc_string\n";
このプログラムコードをファイル名「 substr_replace.pl 」で保存して実行すると次のような結果が得られます。
$ perl substr_replace.pl
string: ハローワールド
substring: ワールド
replace: パール
ハローパール
成功です。
0x246 -> 0x247 へ
Perl での日本語処理がだいぶこなれてきました。僕にとっては、「 プログラムファイルは UTF-8 で作成・保存する 」するという知識がクリティカルだったように思います。
なお、デコード / エンコード に利用しているモジュール「 Encode.pm 」には、より便利な関数が様々に用意されています。興味のある方は
Encode.pm - CPAN 等を確認してみてください。
また、Perl での デコード / エンコード には「 Encode.pm 」以外の選択肢も用意されています。まずは、
Perl Unicode FAQ - perldoc.jp あたりを読んで見るとよいかもしれません。
次回は、「 printf 」によく似た関数「 sprintf 」を確認します。
参考情報は書籍「 初めての Perl 第 6 版 」を中心に perldoc, Wikipedia および各 Web サイト。それと詳しい先輩。
目次 - Perl Index