ぱるも日記

ぱるも日記は id:palmo がプログラミング言語 Perl を1から勉強していく日記です。

2006-07-09 Hello, CGI!

配列ハッシュHTML で出力する

先ほどのエントリでは HTML 文によりページを表示しましたが、ただ単に HTML 文を print しているだけだったので、これでは HTML ファイルを表示してるのと、なんら変わりません。

そこで、今度は変数を埋め込んでページを表示してみます。スカラーは p 要素として、配列は ol 要素として、ハッシュは dl 要素として表示してみたいと思います。

関数に切り分けたら、ちょっと長くなりましたが、こんな感じになりました。

#!/usr/local/bin/perl

use strict;

sub print_array(\@) {
    print "<ol>\n";
    print "<li>$_</li>\n" for (@{ $_[0] });
    print "</ol>\n";
}
sub print_hash(\%) {
    my $h = shift;
    print "<dl>\n";
    print "<dt>$_</dt><dd>$h->{$_}</dd>\n" for (keys %$h);
    print "</dl>\n";
}
sub print_var {
  while (my $v = shift) {
    my $type = ref($v);
    if    ($type eq '')       { print "<p>$v</p>\n"; }
    elsif ($type eq 'SCALAR') { print "<p>$$v</p>\n"; }
    elsif ($type eq 'ARRAY')  { print_array(@$v); }
    elsif ($type eq 'HASH')   { print_hash(%$v); }
    elsif ($type eq 'REF')    { print_var($$v); }
    else                      { print "<p>$type</p>\n"; }
  }
}

# メイン処理
{
    print "Content-Type: text/html\n\n";
    print <<HEADER;
<html>
<head><title>Printing Variables</title></head>
<body>
HEADER

    my $sc = "Hello, my name is Palmo!";
    my $ar = ["First", "Second", "Third"];
    my $ha = {Apple => "Red", Banana => "Yellow", Peach => "Pink"};

    print_var($sc, $ar, $ha);

    print <<FOOTER;
</body>
</html>
FOOTER
}

print_array 関数は、渡された配列を ol 要素として出力します。同じく print_hash 関数は渡されたハッシュを dl 要素として出力します。これらの関数プロトタイプによってリファレンスを受け取るようになっています。リファレンスをやりとりする事で、無駄なコピーを抑える事ができます。

print_var 関数は、渡された値のリストをそれぞれ HTML で出力します。ref 関数スカラー変数の中身がリファレンスじゃないなら空文字を、リファレンスなら「何」を参照しているのかを表した文字列を返してくれるのでしたね。これを利用して、リファレンスが渡された時も、中身を適切に表示できるようにしました。if 文が羅列していて、ちょっと汚いですね……。(^_^;)

メイン処理でページを表示しています。$sc はスカラー値、$ar は無名配列へのリファレンス、$ha は無名ハッシュへのリファレンスがそれぞれ入りますね。これを print_var 関数に渡すと、ちゃんと表示してくれるはずです。

var2html.cgi 実行結果

上手く表示できました。(^_^)


ところで if 文の羅列が嫌な時は「Switchモジュールを使えば良いそうです。このモジュールを use すると、C言語などでお馴染みの switch 構文が使えるようになります。

Switch モジュールを使って上のスクリプトの print_var 関数を書き換えると、以下のようになります。

use Switch;

sub print_var {
  while (my $v = shift) {
    switch (my $type = ref($v)) {
        case ''        { print "<p>$v</p>\n"; }
        case 'SCALAR'  { print "<p>$$v</p>\n"; }
        case 'ARRAY'   { print_array(@$v); }
        case 'HASH'    { print_hash(%$v); }
        case 'REF'     { print_var($$v); }
        else           { print "<p>$type</p>\n"; }
    }
  }
}

if 文を羅列するよりは、断然読みやすいですね。

Switch モジュールによる switch は、C言語switch よりも優れていて case 文には数値に限らず色々な条件を書く事ができます。上のように文字列による case も可能ですし、リストやハッシュなどを書けばその中に switch 対象が存在するかどうか調べられ、正規表現を書けばマッチングが行なわれ、コードブロックを渡せば対象を引数として実行されてその返り値が調べられます。

何でもありですね。(^_^;)

fbisfbis 2006/07/10 10:59 段階を経て勉強しているのなら余計なお世話かもしんないんでつっこむべきかどうかちょっと迷ったんですが、HTMLを出力するのであればHTML::TemplateなりTemplate-Toolkitなりのテンプレートエンジンを利用した方が良いかと。まずはシンプルなHTML::Templateとかどうですか。

palmopalmo 2006/07/10 14:58 なるほど、モジュールを使ってHTMLを出力するのですね。教えて頂いた HTML::Template、とても便利で面白そうです。じっくり勉強したいと思います。また、よく見かける CGI モジュールも勉強する予定です。
ツッコミはとても助かります。何せノウハウや経験が無いので、どのようなモジュールやアプローチが一般的に使われているのかわからず、手探りで勉強している状態なので……。(^_^;)
ありがとうございます!

cuLEkYnuqEcuLEkYnuqE 2006/09/15 15:48 IIi0W7Ir2Cm0 VIGSvKajS0sc67 lkSaGz2Tj5

あsdあsd 2006/11/17 13:19 sddd

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証