Perl
日本語
 Perlを作ったのはLarry Wallである。アメリカ人だから、当然英語を基盤として考えている。それでPerlをそのまま日本語で使うと変なことが起こる。次のコードをshiken.plと名づけて実行してみてほしい。
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;

my ($mojiretsu, $suji);

$mojiretsu = "Larry Wall";
$suji = length($mojiretsu);
print $mojiretsu . "は" . $suji . "文字です。\n";

$mojiretsu = "山本 弘";
$suji = length($mojiretsu);
print $mojiretsu . "は" . $suji . "文字です。\n";
 次のように表示される。
Larry Wallは10文字です。
山本 弘は12文字です。
 Larry WallはLarryが5文字、Wallが4文字だから、合わせると9文字である。しかし中にスペースがあるから、これを1文字と考えると10文字になる。確かに10文字で合っている。
 しかし「山本 弘」が12文字というのは、どういうことだろうか。これは中のスペースを考えても4文字でなければならない。lengthはPerlで文字数を返す関数である。しかしlengthをそのまま日本語に使うと文字数を表示することができない。
 実はこの12というのは、「山本 弘」のバイト數を表している。バイトは単位であり、英語ではbyteである。コンピューターは2進法の0、1が最小単位になっている。これがビット(英語でbit)である。1ビットは0、1の2通りである。8ビットは2の8乗、28で256通りある。アルファベットは26文字であるから、大文字、小文字の区別やよく使う記号などを考えても、256通りあれば、日常使うものはすべて表すことができるだろう。だからアルファベットなどは8ビットで表している。8ビットが一つの単位になるから、8ビットを1バイトと言っている。日本語はアルファベットも使うが、ひらがながあり、カタカナがあり、漢字がある。漢字の種類は非常に多い。日本人でも読むことができない漢字や書くことができない漢字はたくさんある。1バイト、256通りではすべての文字を表すことはできない。それで日本語の文字はだいたい3バイトあてている。3バイトは256の3乗だから、16777216通りある。1677万7216通りあるのだから、日本人が日常使う文字はまず表すことができるだろう。
length("山本 弘");
で返される12は「山本 弘」のバイト数を表している。1文字が3バイトだから、「山本 弘」は12バイトになる。全角スペースも3バイトである。
 文字数を知りたいのに、バイト數を返されても困る。日本語の文字数を返すにはどうすればよいのだろうか。次のように
use utf8;
を入れてみる。utf8 は文字コード規格「Unicode」を符号化する方式の一つである。Unicodeはほとんどの漢字にもコードを割り当てている文字コードである。
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use 5.010;

my ($mojiretsu, $suji);

$mojiretsu = "Larry Wall";
$suji = length($mojiretsu);
print $mojiretsu . "は" . $suji . "文字です。\n";

$mojiretsu = "山本 弘";
$suji = length($mojiretsu);
print $mojiretsu . "は" . $suji . "文字です。\n";
 これをshiken2.plと名づけて実行すると、次のように表示される。
Larry Wallは10文字です。
Wide character in print at shiken2.pl line 15.
山本 弘は4文字です。
「山本 弘」は4文字だというのだから、これは正確に文字数を返している。文字コードとしてUTF-8を使用することをuseを使って明示すればいいのである。しかし問題がある。
Wide character in print at shiken2.pl line 15.
というエラー表示が出るのである。
「use utf8;」をつけると、すべての文字列にUTF8フラグがつく。このUTF8フラグがついている文字列がwide characterである。つぎに「use utf8;」のかわりに、
use encoding ("utf-8");
を使ってみる。
#!/usr/bin/perl
use strict;
use warnings;
use encoding ("utf-8");
use 5.010;

my ($mojiretsu, $suji);

$mojiretsu = "Larry Wall";
$suji = length($mojiretsu);
print $mojiretsu . "は" . $suji . "文字です。\n";

$mojiretsu = "山本 弘";
$suji = length($mojiretsu);
print $mojiretsu . "は" . $suji . "文字です。\n";
 これをshiken3.plと名づけて実行すると、次のように表示される。
Larry Wallは10文字です。
山本 弘は4文字です。
 これは正確に文字数を返しており、wide characterというエラー表示も出ない。  「use encoding "utf-8"」という指定は、標準入出力の文字コードとしてutf-8 を使い、スクリプトはutf-8で記述されていると見なすという指定である。これを使うとwide charcterのエラー表示は出ない。次に正規表現を試してみる。
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;

my ($mojiretsu, $suji);

$mojiretsu = "Larry Wall";
if ($mojiretsu =~ /\w+/){
	print $mojiretsu . "は文字列です。\n";
}
else{
	print $mojiretsu . "は文字列でありません。\n";
}

$mojiretsu = "山本 弘";
if ($mojiretsu =~ /\w+/){
	print $mojiretsu . "は文字列です。\n";
}
else{
	print $mojiretsu . "は文字列でありません。\n";
}
 これをshiken4.plと名づけて実行すると、次のように表示される。
Larry Wallは文字列です。
山本 弘は文字列でありません。
 正規表現で\wは文字1文字を表し、+は一つ以上の繰り返しを表す。だから、\w+で文字列になる。「Larry Wall」は文字列と認識しているが、「山本 弘」は文字列と認識していない。これでは、正規表現は日本語で使えないことになる。次に
use encoding ("utf-8");
を加えてみる。
#!/usr/bin/perl
use strict;
use warnings;
use encoding ("utf-8");
use 5.010;

my ($mojiretsu, $suji);

$mojiretsu = "Larry Wall";
if ($mojiretsu =~ /\w+/){
	print $mojiretsu . "は文字列です。\n";
}
else{
	print $mojiretsu . "は文字列でありません。\n";
}

$mojiretsu = "山本 弘";
if ($mojiretsu =~ /\w+/){
	print $mojiretsu . "は文字列です。\n";
}
else{
	print $mojiretsu . "は文字列でありません。\n";
}
 これをshiken5.pl名づけて実行すると、次のように表示される。
Larry Wallは文字列です。
山本 弘は文字列です。
 「山本 弘」も文字列として認識している。日本語で正規表現を使う時、
use encoding ("utf-8");
を書いておけばいいのである。
 次に文字の重なりを認識するかどうか見てみる。次のようなコードを書き、shiken6.plと名づける。
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;

my ($mojiretsu, $suji);

$mojiretsu = "Larry";
if ($mojiretsu =~ /(\w)\1/){
	print "「" . $mojiretsu . "」は" . "「" . $1 . "」が重なっています。\n";
}
else{
	print "「" . $mojiretsu . "」は" . "は文字が重なっていません。\n";
}
#\1は()の中の\wで一致するものを返す。

$mojiretsu = "足跡が点点とある。";
if ($mojiretsu =~ /(\w)\1/){
	print "「" . $mojiretsu . "」は" . "「" . $1 . "」が重なっています。\n";
}
else{
	print "「" . $mojiretsu . "」は" . "文字が重なっていません。\n";
}
(\w)\1
で\1は()の中で一致するものを返す。だからこれで文字の重なりを表す。これを実行すると、
「Larry」は「r」が重なっています。
「足跡が点点とある。」は文字が重なっていません。
と表示される。「Larry」のほうは「r」の重なりを認識するが、「足跡が点点とある。」のほうは「点」の重なりを認識しない。これでは日本語に正規表現は使えない。shiken6.plのコードに
use encoding ("utf-8");
を加えてみる。
#!/usr/bin/perl
use strict;
use warnings;
use encoding ("utf-8");
use 5.010;

my ($mojiretsu, $suji);

$mojiretsu = "Larry";
if ($mojiretsu =~ /(\w)\1/){
	print "「" . $mojiretsu . "」は" . "「" . $1 . "」が重なっています。\n";
}
else{
	print "「" . $mojiretsu . "」は" . "は文字が重なっていません。\n";
}
#\1は()の中の\wで一致するものを返す。

$mojiretsu = "足跡が点点とある。";
if ($mojiretsu =~ /(\w)\1/){
	print "「" . $mojiretsu . "」は" . "「" . $1 . "」が重なっています。\n";
}
else{
	print "「" . $mojiretsu . "」は" . "文字が重なっていません。\n";
}
 実行すると、次のように表示される。
「Larry」は「r」が重なっています。
「足跡が点点とある。」は「点」が重なっています。
 「足跡が点点とある。」の「点」も重なっていることを認識している。正規表現を日本語に使う時は
use encoding ("utf-8");
を加えておけばいいのである。

Wide character in print の対処法
日本語の処理をするために、use utf8 を私用すると、よく Wide character in print のエラー表示が出る。次のコードをshiken21.plとして実行してみる。
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
my ($seimei, $first_moji);

$seimei = "村上康夫";
$first_moji = substr($seimei, 0, 1); 
print $first_moji, "\n";
次のように表示される。
Wide character in print at shiken21.pl line 9.
村
このエラーが出ないようにするには、
use utf8;
でなく、
use encoding ("utf-8");
を用いる。
#!/usr/bin/perl
use strict;
use warnings;
use encoding ("utf-8");
my ($seimei, $first_moji);

$seimei = "村上康夫";
$first_moji = substr($seimei, 0, 1); 
print $first_moji, "\n";
次のように表示される。
use utf8;
のままでも、print の前に
use bytes;
をつけると、このエラーは出なくなる。
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
my ($seimei, $first_moji);

$seimei = "村上康夫";
$first_moji = substr($seimei, 0, 1); 
use bytes;
print $first_moji, "\n";
use Encode;
を使う方法もある。
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use Encode;
my ($seimei, $first_moji);

$seimei = "村上康夫";
$first_moji = substr($seimei, 0, 1); 
$first_moji = encode("utf-8", $first_moji);
print $first_moji, "\n";
更新日:2023年1月24日

ホームにもどる      「パソコンについて」にもどる