モダンPerlの世界へようこそ

第40回 Text::MicroTemplate:得意分野なんだからPerlを使えばいいじゃない,という方に

この記事を読むのに必要な時間:およそ 5 分

テキストの整形はPerlの基本

Perlは「Practical Extraction and Report Language」とも呼ばれるくらいで,正規表現などによる情報抽出機能と並んで,レポートの形を整えて出力する機能はPerlの根幹をなす部分といえます。もちろんそのもっとも原始的な形は二重引用符でくくられた文字列のなかにそのまま変数を埋め込むものです。

print "This report is created by $author.";

もう少しこったことをしたければ,Cから受け継いだprintf系の構文を使えばよいでしょう。

printf "This report is created on %04d/%02d/%02d.", $year, $month, $day;

優先順位の都合でうまく埋め込めなかったり,改行などを含む長い文字列を出力する場合は,適当なところで区切って,ドットで結合したりカンマでつなげたり(念のため,単に出力するだけならカンマで区切るほうがかなり速くなります)⁠

use Time::Piece;
print "This report is created by $author",
      "on ".Time::Piece->new->ymd.".\n",

あるいはシェルから受け継いだヒアドキュメントを使う手もあるのでした。

printf <<"END", $year, $month, $day;
This report is created by $author,
on %04d-%02d-%02d.
END

また,連載第31回でも紹介したように,いまとなっては多くの問題を抱えているものの,古くからのPerlユーザのなかにはいまなおFORTRANから借りてきたformatを愛用している人もいるようです。

format STDOUT = 
This report is created by @*,
$author
on @*-@*-@*.
$year, $month, $day
.

write;

ただし,これらの組み込み関数を利用した整形・出力は,いずれもあまり再利用性は高くありません。また,見栄えの調整をするにもプログラミングの知識が必要になるため,書式を複数のスクリプトで使い回したり,プログラミングが専門ではない人に作業に委託するような分野では,もう少し融通の利くテンプレート処理用のモジュールを利用するのがふつうです。

例によって多様性を重視するPerlの世界では有名どころだけでも片手では数えられないだけのテンプレートモジュールがありますが,代表的なものを大別すると,1)生のPerlコードをテンプレート内に埋め込めるようになっているものと,2)独自のタグ言語が用意されているものに二分できます。また,後者については,2-a)テンプレート内でオブジェクトのメソッドなどを呼び出すことはできないものと,2-b)メソッド呼び出しが可能なものにわけることもできます。また,厳密にはテンプレートエンジンとはいえないものの,3)特定のタグを出力するヘルパー関数を多用してテンプレート(もどき)を構成するものも同列に扱ってもよいかもしれません。これらはそれぞれ得意な分野も異なりますし,モジュールの選択によってはコードの書き方ががらりと変わってしまうこともありえるので,できればそれぞれの特徴をおさえた上で自分の用途にあったものを選択したいものです。

今回からは何度かにわけてテンプレートまわりのモジュールについてまとめてみます。初回の今回は,テンプレートに生のPerlコードを埋め込めるタイプのモジュールを取り上げます。

Text::Template

この系統のモジュールとしてはまずHigher Order Perlなどの著作で知られるマーク・ジェイソン・ドミナス(Mark Jason Dominus)氏が1995年12月にリリースしたText::Templateがあげられます。

これはCPANに登録されているPerlのテンプレート関連モジュールとしては最古のものなので,いまとなってはさすがに古めかしさを禁じ得ませんが,そのドキュメントに書いてある「独自のテンプレートタグは言語としては不完全なものだから,作者が想定していないことをしようとしたときに困る」とか「Perlがあるのに,どうしてわざわざほかのミニ言語を学ぶ必要があるのだろう」という問題提起はいまでも十分通用するものです。

Text::Templateの機能自体はヒアドキュメントに毛が生えたようなもので,テンプレート内部で一部の要素を条件文やループでくくるような記述はできません。ただし,ヒアドキュメントが@{[...]}などの熟語を使うことで任意の式を埋め込めるように,Text::Templateも,最終的に埋め込む値を返しさえすれば,ブロックの中に任意の文を埋め込むことはできます。サンプルには,比較のため,ヒアドキュメントの例もいっしょに並べてみました。ヒアドキュメントの@{[...]}の中にはふつうセミコロンを含む文は入れられませんが,ここではdo { } でくくることで対応しています。

ヒアドキュメントの場合

use strict;
use warnings;

my $author = 'me';
my @items = (1, 2, 3);

print <<"END";
This report is created by ${author}.
@{[ do {
  my $list = '';
  for (@items) { $list .= "item $_\n" }
  $list; # 最終的にこの値が埋め込まれます
}]}
END

Text::Templateの場合

use strict;
use warnings;
use Text::Template;

my $author = 'me';
my @items = (1, 2, 3);

my $template = <<'END';  # ここの部分は外部のファイルに切り出せます
This report is created by {$author}.
{
  my $list = '';
  for (@items) { $list .= "item $_\n" }
  $list; # 最終的にこの値が埋め込まれます
}
END

print Text::Template->new(TYPE => 'STRING', SOURCE => $template)
        ->fill_in(HASH => { items => \@items, author => $author });

この例ではText::Templateに渡すテンプレートもヒアドキュメントで作成しているため違いが見えづらくなっていますが(⁠END」をくくるクォーテーションの違いがポイントです)⁠実際には外部ファイルに切り出したテンプレートでもヒアドキュメントとほとんど同じ書き方ができるのがText::Templateの長所といえます。また,弱点としては,ヒアドキュメントのレベルでは対応がむずかしいループの処理やエスケープ処理などを自前で実装しなければならないことなどがあげられます。

著者プロフィール

石垣憲一(いしがきけんいち)

あるときは翻訳家。あるときはPerlプログラマ。先日『カクテルホントのうんちく話』(柴田書店)を上梓。最新刊は『ガリア戦記』(平凡社ライブラリー)。

URLhttp://d.hatena.ne.jp/charsbar/

コメント

コメントの記入