nanoaでPerlを学習 その3 utf8プラグマ

今回はutf8について.詰め込むにも削るにもなかなか大変です.utf8関連という意味ではいろいろ書くことがありますが,ここではプラグマに絞って書きます

use utf8;

utf8というのは文字コードです.コンピュータ上での文字の表し方のひとつです.ブラウザを使っていればshift_jisとかeuc-jpという単語を見ることがあると思いますが,それの仲間です.どれも日本語も表現できる方法です

というわけでこのuse utf8宣言(これもstrictやwarningsと同じプラグマ宣言です!)は,utf8でソースを書きますよ!という宣言なのです.いつもこんな感じになってしまいますが,この宣言をしておけばソースをutf8をとして扱えるようになるとわかっていれば(とりあえず)読む必要はないかもしれません

ファイルをutf8で保存する

utf8で日本語を表現しますが,ファイルに保存するときにももちろん使われています.いろんなことをすっ飛ばして説明しているのでここまで出てきませんでしたが,このhello/start.pmにも文字コードがあります.そしてその文字コードはutf8じゃないとダメです.utf8を扱えるエディタならutf8で保存することができると思います

別の文字コードで保存したらどうなるのでしょう,たとえばWindowsに付属のメモ帳はWindows標準の文字コードしか扱えません.プログラムをメモ帳で書くとcp932と呼ばれる文字コードになります.cp932にという単語には聞き覚えがないかもしれませんが,Microsoft版のShift_JISです

最初のhello/start.pm

こんにちは、<?= $app->query->param('user') ?>さん

チュートリアルの最初のプログラムをメモ帳で作るとエラーが出ます.プログラムをちゃんと読み込めなかったからでしょう.エラーが出なくてもブラウザでよくある文字化けなども起こるかもしれません.いま説明しているほうのhello/start.pmで使う,hello/template/start.mtをメモ帳で作ると文字化けします

nanoaでプログラムを作るときには,すべてのファイルを必ずutf8で保存しましょう

utf8プラグマって何をする?

最初にも書きましたがPerlソースコードUTF-8で書かれていることを示すプラグマです.このプラグマでUTF-8の文字列・正規表現リテラル・変数名を使えるようになります

具体的なコードだとこんな感じです.ソースコードはutf8で保存されています

#! /usr/bin/env perl

use strict;
use warnings;
use utf8;

my $ぽ;#utf8の変数名を使える
$ぽ = 'ほげほげ';#strの中身はutf8と見なされる

if($ぽ =~ /げほ/) {#match!
    print "match!\n";
} else {
    print "no match...\n";
}

if($ぽ =~ /\343/) {#no match...
    print "match!\n";
} else {
    print "no match...\n";
}

no utf8;#utf8プラグマを無効に

my $str = 'ほげほげ';

if($str =~ /げほ/) {#match!
    print "match!\n";
} else {
    print "no match...\n";
}

if($str =~ /\343/) {#match! マッチしてしまう
    print "match!\n";
} else {
    print "no match...\n";
}

文字をちゃんとバイトコードの集まりではなく,utf8の文字として扱ってくれるので思った通りの動きをしてくれるのです.文字列の長さを表示するlengthなどの動作を見るとわかりやすいかもしれません

#! /usr/bin/env perl

use strict;
use warnings;
use utf8;
print length('あ'), "\n";# 1

no utf8;#utf8プラグマを無効に
print length('あ'), "\n";# 3

このコードもutf8で保存します

「あ」という文字の長さを知りたいので,期待するのはもちろん1です.ですがutf8プラグマが有効でない場合には,utf8での「あ」を表すバイトコード「\343\201\202」と認識し,3という結果が返ります

ひとつ前のソースコードのutf8プラグマが有効でない場合に$str =~ /\343/という正規表現にマッチしてしまったのは「ほげほげ」というutf8の文字列にバイトコードで「\343」が含まれていたからです

文字列がPerlによってutf8と見なされているか調べる

文字列がutf8と見なされているのかを調べる方法があります.Devel::Peekというモジュールをuseすることで使えるようになるDumpという関数を使用します.Devel::PeekはPerl 5.6から標準モジュールですのでutf8を扱えるPerlの環境では間違いなく入っているはずです

#! /usr/bin/env perl

use strict;
use warnings;
use Devel::Peek;

use utf8;
print "[use utf8]\n";
Dump 'あ';

no utf8;#utf8プラグマを無効に
print "[no utf8]\n";
Dump 'あ';

しつこいようですがutf8で保存してください.結果は下記のようになります

[use utf8]
SV = PV(0x3e6944) at 0x9e981c
  REFCNT = 1
  FLAGS = (PADTMP,POK,READONLY,pPOK,UTF8)
  PV = 0x9f8934 "\343\201\202"\0 [UTF8 "\x{3042}"]
  CUR = 3
  LEN = 4
[no utf8]
SV = PV(0x3e7184) at 0x9e97cc
  REFCNT = 1
  FLAGS = (PADTMP,POK,READONLY,pPOK)
  PV = 0x9fb824 "\343\201\202"\0
  CUR = 3
  LEN = 4

utf8プラグマが有効なところで実行されたDumpの結果のFLAGSの部分を見てください.最後にUTF8と書かれています.これが文字列がutf8であるとPerlが認識している印です.utf8フラグと呼ばれています

で,nanoaではどうなの?

nanoaで直接ソースコードにutf8文字列を書くときにはuse utf8を使います.このサンプルコードではuse utf8の必要ありません.実際use utf8をコメントアウトしてもふつうに表示されます.ですが,これもおまじないだと思って書いておくといいかもしれません

最後に

Perlで日本語を使っていると必ずと言っていいほどutf8に関わることになると思います.ひとまずはソースコードに日本語を書くときはuse utf8して,utf8で保存するということを覚えておくといいと思います.ここで書かれていることだけでは文字化けとかで悩まされていろいろ調べることになるでしょうが……