フリーソフトの小道   

コンピュータ・プログラマー養成講座(入門編)

第14回 「Perl入門 @」
CGIとインタープリタ言語 Perl

インタープリター言語

 コンピュータ言語には、インタープリタ型とコンパイラ型の2つのタイプがある。 インタープリタ型言語の体表的名言語はBASICであり、昔のパソコンでは常用言語であった。 現在ではBASICは廃れてしまったようで、パソコンの世界ではJAVAが主流となている。
 UNIXや通信の世界では、インタープリタ型言語は現在でも大いに使いこなされており、 昔は、管理人が大好きな言語 「AWK」 が良く使われていた。 10行ほどの記述で相当な仕事ができる、効率の良い言語である。
 現在では、「AWK」をより発展させたといえる 「Perl」 が主流になっている。 また、日本人による 「ruby」 という言語もある。 それぞれ特徴があるが、インタープリタ言語であるのでコンパイルすることなく、 キー入力するだけですぐに実行できるので、今でも管理人はよく使っている。

Perl言語

 インターネットを運営しているサーバーの世界では、Perl というインタープリタが常用されている。 CGIというサイトのコンテンツを動的(ユーザーに合わせたり、時間にあわせたり)に管理したり、 インターネットアクセスログ(インターネットに接続に関する記録)を取ったり、 システム全体の管理を行うことができる汎用の言語である。
 言語の仕様は、AWK と似ている(Cに似ている)ので、 C言語を理解している人には簡単に修得することができる。例を挙げて説明してみよう。

Perl言語における変数記述のルール

変数を扱うには変数名の先頭に記号をつけるという少し変わったルールがある。 スカラー変数は$、ベクトル(配列)変数は@がつくというもの。 最初は邪魔くさいのですが、変数宣言をすることなく随時どこでも使える便利な(いいかげんな)もの。 下に示す、今回のアクセスログについて、そのソースを示しながら説明してみよう。
 my と先頭についているのは、 このプログラム記述部分にのみ有効な変数(ローカル変数)という意味を表す形容詞になる。 $imgfile とあるのは、普通の変数(スカラー変数)であることを示す文字で、 他の言語では余り見かけないので、Perl特有の表現である。 現在時刻読み取りの部分に @ltime という変数がでくるが、 これはベクトル変数(複数の変数がセットになった配列変数)という。 数学で習うベクトルも x,y,z の3つの座標値をまとめて1つの量として扱うのと同じ考え方である。 この @ltime 変数は $ltime[0]、$ltime[1]、$ltime[2]、$ltime[3]、$ltime[4]、$ltime[5] の5つのスカラー変数を まとめて表しているもので、 $ltime[0] には秒の値が、 $ltime[1] には分の値が、 $ltime[2] には時の値が、 $ltime[3] には日の値が、 $ltime[4] には月の値が、 $ltime[5] には年の値(1900年をゼロとして)が入っている。  今回は、この2つの変数の記名法を説明するだけに留める。 なお、変数には何でもいれることができる。文字でも、数字でも、配列でも何でも入る。 C言語のように変数の内容によって、宣言を区別する必要はない便利なものである。

ファイル入出力

 ファイル入出力の記述も大変簡単で、 ファイルの読み込みはソースリストの最後の部分にある open(FILE,"<$imgfile") と簡単だ。 ファイルの書き出しはソースリストの中ほどにある open(FP,">>$log_file") と同じようなものだ。 不等号の向きが左向きが読み込み、右向きが書き出しである。 書き出しの場合はファイルのゼロからの書き出し(初めての書き出し)では不等号が1つ、 追加書き出し(以前にあるファイルに追記するとき)では不等号が2つになる。 アクセスログは毎回記録を追加してゆく性格上、不等号が2つになっている。、

本日はこれくらいに

 ソースリスト全てを理解するのは無理だから、これくらいにして、 次回以降、Perlについてより詳しい解説をする予定である。

2004/04/10  管理人(志)


「物理の小道」でのアクセスログCGIのソースリスト



#!/usr/local/bin/perl	第一行目に書くおまじないのような文字列

use strict;
use CGI;	CGIライブラリ読み込み

# imagefile	表示する画像ファイル名を指定
my $imgfile="getlog.gif";	myはローカル変数指定、$はスカラー変数を示す

# get referrer
my $cgi=CGI::new();	CGIライブラリ初期化
my $ref=$cgi->param('ref');	受け渡し変数 ref の値の読み込み

# get date
my @ltime=localtime(time);	現在時刻を読み取り、配列ltime に値を書き込む
my $datestr=sprintf("%04d\/%02d\/%02d-%02d:%02d:%02d",
  $ltime[5]+1900,$ltime[4]+1,$ltime[3],$ltime[2],$ltime[1],$ltime[0]);	時刻表示する文字列作成

# get remote host	アクセスしてきたパソコンのIPアドレス情報などを取得
my $host=gethostbyaddr(pack("C4",split(/\,/,$ENV{'REMOTE_ADDR'})),2);
if($host eq "") {$host=$ENV{'REMOTE_ADDR'}; }

# get usrname
my $agent=$ENV{'HTTP_USER_AGENT'};	アクセスしてきたOS、ブラウザの情報を取得


# get pagename
my $page_name=$cgi->param('page_name');	アクセス直前のページの名前

# add to logfile
my $log_file='__accesslog2004__.log';	アクセスログのファイル名(仮称です)
if(open(FP,">>$log_file")) {	追加出力用としてファイルを開く
  flock(FP,2);	2重書き込み防止のための設定
  print FP "${datestr}\t${ref}\t${page_name}\t${host}\t${agent}\n";	アクセス情報をファイルに記録
  flock(FP,8);	2重書き込み防止のための設定を解除
  close(FP);	アクセスログファイルを閉じる
}

# output
print "Content-type: image\gif\n\n";	出力画像のデータを送出する
open(STDOUT);
binmode(STDOUT);
if(open(FILE,"<$imgfile")){	読み込みモードでファイルを開く
  binmode(FILE);
  while(read(FILE, my $buf,1024)) {
    print STDOUT $buf;
  }
  close(FILE);
}
close(STDOUT);
exit;






感想・意見は、掲示板、または メールでどうぞ! --- 管理人(志)