Perl を使おう! 第4回


[ 目次 / 前頁 / 次頁 ]

前回の宿題

  1. Perl スクリプトの記述練習として、「鶴亀算」のプログラム。
  2. 前回の宿題について、連想配列を使いdateコマンドの結果を修正して 「本日は xx月xx日 xx曜日です。」という形式で表示する。また、カウンターを修正し、カウンターの値を各桁の数値の配列にして、配列の先頭から数値に対するカウンターファイルを表示するグラフィックカウンターを作る。(ヒント:数値を""を区切りに配列にとって、while や foreach を利用すればいいでしょう。)
回答例 by yama

この宿題に関連して...

環境変数の利用

Perl では 環境変数(env の表示)は %ENV という連想配列に書き込まれています。 したがって、環境変数から必要な変数を取り出して利用することは簡単です。 例えば、ホームページを参照している利用者のブラウザの種類は $ENV{"HTTP_USER_AGENT"} で取り出せますし、 IPアドレスやホスト名はそれぞれ$ENV{"REMOTE_ADDR"},$ENV{"REMOTE_HOST"}で取り出せます。 従って、環境変数を表示するスクリプトは
  === [begin] printENV.pl =====
  @envkey = keys(%ENV);
  foreach $a (@envkey){
    print "$a : $ENV{$a} \n";
  }

  実行
    %perl printENV.pl
    結果表示
の様に書くことができます。当然こんな表示をブラウザに表示するのは面白くないので、テーブルに奇麗に入れて表示するCGIスクリプトを書きましょう。
    ==  [tableENV.cgi]  ==
環境変数のテーブル出力
これを知っていれば、必要な時に必要な環境変数を利用することができそうですね。


実行時引数を受けるプログラム

宿題の1では、鶴亀算の計算をプログラムが起動してから、頭と足の数を聞くように プログラムしましたが、プログラム実行時にパラメータを直接渡す方法でプログラムを書き直しましょう。 Perl ではパラメータは空白区切りで渡します。 渡されたパラメータはプログラム内では@ARGV という配列で参照できます。 したがって、解答例のプログラムは、次のように書き換えられます。
    ==  [tsurukame.pl]  ==
    実行
    % tsurukame.pl 4 12
    鶴は 2 羽
    亀は 2 匹
    %
このように変更することにより、コマンドラインから引数を渡すことが可能になります。 更に、ホームページでフォームに入力された値に対してこの計算の結果を返すにはどうすれば良いのでしょうか?

フォームからの入力を処理する CGI プログラミング

フォームからデータを入力するためには、HTML の知識が必要になります。 そこで、フォーム機能について予備知識のないかたは
      HTMLリファレンスからフォームについて  <-- ここを参照して下さい。
ということで、フォームから入力されたデータをCGIプログラムで利用するには幾らか処理が必要になります。 ここでは、鶴亀算の計算を入力形式に変更してみることを試みます。 必要なフォームを作り、それを処理するスクリプト test.cgi を用意します。
まず、第一にどのような形で入力が渡されているを確認して見ます。 METHOD="GET" を指定した場合には、環境変数 QUERY_STRING に格納されるということなので、test1.cgiとして
    ==  [cgi-bin/test1.cgi]  ==
    ドキュメントソース
    <FORM ACTION="/~yama/cgi-bin/test1.cgi" METHOD="GET">
     頭の数: <INPUT TYPE="text" SIZE=5 NAME="head">
     足の数: <INPUT TYPE="text" SIZE=5 NAME="foot"><P>
     <INPUT TYPE="submit" VALUE="計算">
     <INPUT TYPE="reset" VALUE="入力しなおす">
    </FORM>
とすると確認できそうです。

頭の数: 足の数:

この結果を見てわかるように、フォームで入力されたものは

    フォーム名=値&フォーム名=値
の形式で格納されるのがわかります。ではこれらを分離してみましょう。
    ==  [cgi-bin/test2.cgi]  ==
頭の数: 足の数:


うまくいったようですね。 ではさきほどの鶴亀算のプログラムを修正しましょう。
    ==  [cgi-bin/test.cgi]  ==
頭の数: 足の数:


最後にHTMLとして表示するものにして完成です。
鶴亀算
頭の数: 足の数:


また、ここでは鶴亀算のプログラム自身を修正しましたが、鶴亀算の計算プログラムをCGIとしても、通常のコマンドラインから実行するプログラムとしても使用できるようにするために計算プログラムとCGI用のプログラムを分けて記述すると良いでしょう。
    ==  [cgi-bin/tsuruka.pl]  ==

実行
% tsuruka.pl 4 12

これを利用するようにCGIで利用するプログラムを修正します。 ふう..

Perl 言語 その3

  1. 入出力

    STDIN からの入力

    標準入力からデータを読み込むのは
        $a = <STDIN>
    
    とスカラーコンテキストで評価することにより1行読み込みます。 現在の行から残りの行を全て読み込むためには配列コンテキストで評価します。 よく使われる表現は以下のような使い方です。
        while ($_ = <STDIN>) {
          chop($_);
          $_ に関する処理
        }
    
    Perl では <STDIN> をスカラー変数に読み込みループの制御式として使用することが多いので、$_ を使う略記法が用意されています。 また、$_ を演算子のオペランドと使用する場合はほとんど、演算子の引数を省略できます。
        while (<STDIN>) {  #while ($_=<STDIN>)と同じ
          chop;                  #chop($_) と同じ
          $_ に関する処理
        }
    

    ダイヤモンド演算子

    ダイヤモンド演算子 <> は <STDIN> と同様にスカラーコンテキストでは1行、配列コンテキストでは複数行を読み込みますが、さらにコマンドラインからの引数であるファイルを読み込みます。 例えば、次のファイル mycat.pl
        #!/usr/bin/perl
        while (<>) {
          print $_;
        }
    
    の実行時にファイル名を渡す
    
        % mycat file1 file2
    
    とした場合には、既にわかっているように cat と同じ働き file1の内容とfile2の内容を続けて返すプログラムになります。 また、引数を何も与えなかった場合には、標準入力を読み込みます。

    ダイヤモンド演算子はコマンドライン引数が与えられている場合には、それを読みにいきます。 Perl ではコマンドライン引数は @ARGV という配列に読み込まれます。 従って、@ARGV に値がセットされている時には、ダイヤモンド演算子はそれを読み込みます。

    STDOUT への出力

    これまで、標準出力へテキストを表示するのに print を使用しました。 print は文字列のリストを受け取って、それらを順に標準出力へと送ります。

        print("Hello", " yama", "  1+2=",1+2,"\n");
        print "Hello", " yama", " 1+2=",1+2,"\n";
    
    のように使えます。ただし、最初に表示するものが ( で始まってる場合は全体をカッコで囲まなければなりません。

    また、出力形式をもっと細かく指定したい場合には、printf を利用します。

        printf "%15s %5d %10.2f\n", $s, $n, $r;
    
    上の表示は、$sを15文字幅、空白、$nを5文字幅、空白、$rを10文字幅に小数点以下2桁で表示し改行、を指定しています。詳しくは printf のマニュアル(man printf)で参照して下さい。

  2. ユーザー関数の定義

    関数や手続きは、サブルーチン sub で行なう。

        sub subname {
          statements;
        }
    
    サブルーチン名もまた、別の名前空間として扱われるので、スカラー変名、配列変数名、連想配列名などで使用されている名前と重複しても問題はない。 サブルーチンは、メインとは区別し、ファイルの最後に置いても良いし、Pascal風にファイルの先頭に置いても良い。 メインからはサブルーチン名の前に & をつけることにより呼び出される。

    例)サブルーチンを利用した Hello, world!

        &hello;
      
        sub hello{
          print "Hello, world\n";
        }
    
    サブルーチンの呼び出しによってサブルーチンの中で最後に評価された式が戻り値として返される。
        $a=2; $b=3;
        $c=&sum_ab;
    
        sub sum_ab {
            $a+$b;
        }
    
    上のサブルーチン sum_ab では、 $a + $b のを評価した結果が返り値として返される。 配列コンテキストが評価された場合には配列が返される。

    サブルーチンに引数を渡す場合は、 &サブルーチン名の後ろにカッコで囲んだリストを置く。 サブルーチン内では、特別な配列変数 @_ にその内容が取り込まれる。

        $a="yama";
        &hello($a);
        
        sub hello {
          print "Hello, $_[0]!\n";
        }
    
    -----
        $a=2; $b=3;
        $c=&sum_ab($a,$b);
        print "$a + $b = $c";
        sub sum_ab {
            $_[0]+$_[1];
        }
    
    -----
        $mean = &mean(@ARGV)
        sub mean {
          $sum = 0;
          $length = @_;
          foreach $_ (@_) {
            $sum += $_;
          }
          $sum/$length;
        }
    

    局所変数
    関数内で局所変数を使用する場合には local() 演算子を使用する。

        sub mean {
          local($sum);
          $sum = 0;
          $length = @_;
          foreach $_ (@_) {
            $sum += $_;
          }
          $sum/$length;
        }
    

宿題!

  1. カウンタースクリプトをログ(アクセス時刻、アクセスした相手のホスト名とブラウザ名)をカンマ区切りで記録し、引数としてファイル名を指定するように修正。 (例えば、index.html のカウンターに対しては実行時引数として index を与え、カウンターファイル名を .num-index ロックファイル名を .lock-index ログファイル名を log-index とする。)

[ 目次 / 前頁 / 次頁 ]
最終更新時刻
By Yoshiro Yamamoto