正規表現

  パソコンの文字コードはASCIIが標準である。これはAmerican Standard Code for Information Interchangeの略である。英語は26文字のアルファベットといくらかの記号で表現できてしまう。漢字がたくさんある日本語や中国語に比べると、必要な文字数ははるかに少ない。パソコンはアメリカで発達したため、英語が標準になっている。日本語を表現するには、ASCIIよりはるかにたくさん文字がいるわけで、シフトJISコード、EUC、UNICODEなどの文字コードがある。UNICODEは符号化の形式でUTF-8やUTF-16などがある。UTFはUnicode Transformation Formatの略である。UTF-8が一番よく使われている。
  正規表現(regular expression)も英語から発達したから、ASCIIを前提として発達した。だからそれをそのまま日本語に使おうとすると変なことが起こる。日本語に正規表現を使うことを考えてみる。

#!/usr/bin/perl
use strict;
use warnings;
use 5.010;

my $moji = "Smith";
if ($moji =~ /\w+$/) {
   print "${moji}は文字です", "\n";
}
else {
   print "${moji}は文字でありません", "\n";
}
をshiken1.plと名付けて
perl shiken1.pl
と実行する。
Smithは文字です
と表示される。正しく判断している。正規表現で\wは1文字を表す。wはwordのwを取っている。「${moji}は文字です」と{}をつけているのは、{}がないと、「$mojiは文字でありません」 を一つの変数と取られ、エラーになるからである。\w+ と + をつけるのは、\wは1文字だけだから、1文字以上ですと言いたいのである。つぎに次のshiken2.plを実行してみる。

#!/usr/bin/perl
use strict;
use warnings;
use 5.010;

my $moji = "スミス";
if ($moji =~ /\w+$/) {
   print "${moji}は文字です", "\n";
}
else {
   print "${moji}は文字でありません", "\n";
}

スミスは文字でありません
と表示され、正しく判断していない。日本語になると、正規表現が使えていないのである。日本語で正規表現が使えないなら、正規表現は日本人にとって役に立たないことになる。shiken2.pl は、ASCII を前提として正規表現を使っている。ASCII文字には、「ス」も「ミ」もないから、ASCIIで考えるなら、「スミスは文字でありません」という判断は正しい。日本語を正しく扱うために、文字コードにUTF-8を使うということを明示してみる。use utf8; を入れたshiken3.plをつくる。

#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use utf8;

my $moji = "スミス";
if ($moji =~ /\w+$/) {
   print "${moji}は文字です", "\n";
}
else {
   print "${moji}は文字でありません", "\n";
}

これを実行すると
Wide character in print at shiken3.pl line 9.
スミスは文字です
と表示される。「スミスは文字です」と「スミス」は文字であることを認識している。しかし「Wide character in print at shiken3.pl line 9.」というエラーが出てしまった。shiken3.pl は use utf8; と書いてあるため、ASCII以外の文字ははUTF-8フラグを立てる。UTF-8フラグがついている文字がWide characterで、これはUTF-8の文字と違うから、Wide characterがありますというエラーが出るのである。このUTF-8フラッグをなくするには、UTF-8のコードにencodeしてやればいいのである。shiken4.plを次のように書く。

#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use utf8;
use Encode;

my $moji = "スミス";
my $en_moji = Encode::encode("utf-8", $moji);
if ($moji =~ /\w+$/) {
   print "${en_moji}は文字です", "\n";
}
else {
   print "${en_moji}は文字でありません", "\n";
}

これを実行すると、
Wide character in print at shiken12.pl line 11.
スミスは文字です
と表示される。やはりWide characterのエラーが出るばかりか、今度は文字化けまで出てしまった。これは、
my $en_moji = Encode::encode("utf-8", $moji);
で確かに、$en_mojiのUTF-8フラッグはなくなったのだけど、「${en_moji}は文字でありません 」でプログラムを実行しているため、UTF-8フラッグのない「${en_moji}」と「は文字でありません」が結びつき、「${en_moji}にUTF-8フラッグがないため、正常なプログラムの実行ができず、文字化けを起こしたのである。さらにプログラムを実行したため、「${en_moji}は文字でありません 」にまたUTF-8フラッグがついたのである。それで、shiken5.plのように書き直した。

#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use utf8;
use Encode;
my $en_moji;
my $moji = "スミス";
my $hyoji = "${moji}は文字です";
my $hyoji_not = "${moji}は文字でありません";
$hyoji = Encode::encode("utf-8", $hyoji);
$hyoji_not = Encode::encode("utf-8", $hyoji_not);
if ($moji =~ /\w+$/) {
   print $hyoji, "\n";
}
else {
   print $hyoji_not, "\n";
}

これを実行すると、
スミスは文字です
と表示され、正規表現が日本語でも使えることが確認された。
my $hyoji = "${moji}は文字です";
my $hyoji_not = "${moji}は文字でありません";
のような、プログラムを実行する所はUTF-8フラッグのある形で実行し、最後の$hyojiや$hyoji_notを表示する所だけは、UTF-8フラッグのない形で表示させた。

更新日:2019年9月22日

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