perlでCGIを書く(1)
形式
perlで書く場合、決められた形式はありません。また、変数の型宣言も必要ありません。
1行目は #! で始まり、そのサーバーにあるperlまでのパスを記入します。
1行目は #! で始まり、そのサーバーにあるperlまでのパスを記入します。
例)#! /usr/local/bin/perlコマンド"perl"というインタプリタに、プログラム名"perl"を引数で渡すことによって以下のプログラムが実行されます。
文法 (syntax)
- 各行の終わりは ; (セミコロン)
- ループは { } (ブラケット)
- 条件式が成立した場合に実行される部分も { } 例)if($a == 1) { print; }
- エスケープには \ (バックスラッシュ)
- サブルーティンへ飛ぶには & (アンパサンド)
- 改行は \n
出力形式
通常のテキストを出力する場合
画像を出力する場合(例として GIF を出力する場合)
print "Content-type: text/html\n\n";
画像を出力する場合(例として GIF を出力する場合)
print "Content-type: image/gif\n\n";
出力
print命令を使ってSTDOUTに出力します。
#! /usr/local/bin/perl print "Content-type: text/html\n\n"; print "Hello World\n"; exit(0);print命令によってSTDOUTに出力されたデータ(上記では"Hello World"の文字列)は、WWWサーバーを介してブラウザに渡されます。
変数と代入
上記の"Hello World"は、以下のように書いても同じ表示をします。
文字列を分割して代入することも出来ます。
#! /usr/local/bin/perl print "Content-type: text/html\n\n"; $hello = "Hello World\n"; print "$hello\n"; exit(0);文字列をprint命令で出力する代わりに、スカラー変数($hello)に代入して置き換えています。
文字列を分割して代入することも出来ます。
#! /usr/local/bin/perl print "Content-type: text/html\n\n"; $hello = "Hello "; $world = "World\n"; print "$hello$world\n"; exit(0);
データの受け入れ
上記のサンプルCGIでは、変数$helloや$worldの値を変更することで、表示を"Hello Asia"にも"Goodby Europe"にも変えることができます。
プログラムに渡されたデータは標準入力(STDIN)から取り込む方法と、クエリストリング(QUERY_STRING)から取り込む方法が用いられます。
STDINから取り込む場合(post);
QUERY_STRINGから取り込む場合(get);
プログラムに渡されたデータは標準入力(STDIN)から取り込む方法と、クエリストリング(QUERY_STRING)から取り込む方法が用いられます。
STDINから取り込む場合(post);
read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'});
STDINにはデータ本体が入り、環境変数'CONTENT_LENGTH'にはデータの長さが入ります。STDINはEOFや改行では終わらないので、read関数を使い、長さを指定してバイトを取って来る必要があります。QUERY_STRINGから取り込む場合(get);
$buffer = $ENV{'QUERY_STRING'};
'QUERY_STRING'からは、長さ分のデータがそのまま引数としてプログラムに渡されます。データの長さには制限がありますので、大きなデータを渡す場合はpostを指定します。
デコード
入力されたデータをそのまま表示してみると、
次に"="で分割し、左辺を$keyに、右辺を$valueに格納してやることで、$keyを指定してやれば右辺が参照できるようになります。
このキーワードは、入力されたフォームのネーム指定に対応します。
hello=Good+Night%21+&world=Europe%0D%0Aデータが%や=や+などの記号と共に、スペースなしで表示されます。それらを元の形に戻してやる作業がデコードです。
@pairs = split('&', $buffer);
foreach(@pairs) {
($key, $value) = split("=");
$value =~ tr/+/ /;
$value =~ s/%(..)/pack('c',hex($1))eg;
$in{$key} = $value;
}
$bufferに代入された1列のデータを、'&'の文字が出て来た所で分割(=split)して配列(@pairs)に格納します。ここでデータは、
hello=Good+Night%21+ world=Europe%0D%0Aと、2つに分割されています。
次に"="で分割し、左辺を$keyに、右辺を$valueに格納してやることで、$keyを指定してやれば右辺が参照できるようになります。
$key[0] = hello, $value[0] = Good+Night%21+ $key[1] = world, $value[1] = Europe%0D%0Atr///演算子で+をスペースに変換したあと、置換演算子s///で%21だの%0D%0Aだのといった宇宙語(実は16進数)を元の形に戻してやります。
$key = hello, $value = Good Night! $key = world, $value = Europe\nこうすることで、$in{}のキーワード指定による$valueの値の代入が可能になります。
$in{'hello'} = "Good Night!";
$in{'world'} = "Europe\n";
と書かれたものと同じ意味を持つことになります。このキーワードは、入力されたフォームのネーム指定に対応します。
ヒアドキュメント
まとまった量のテキスト(HTMLなど)をスクリプト中に埋め込む時に使用します。
この文字列は任意に決めて構いませんが、通常は大文字で書かれるのが慣例です。
print <<"END_OF_HTML"; <html><body> 普通のHTMLと同じように書いても<br> エラーにならないんだよ!<br> </body></html> END_OF_HTML<<の直後にデータの終わりを示す文字列を挿入することで、次に同じ文字列が書かれるまでの間をクォートされているものとみなされます。
この文字列は任意に決めて構いませんが、通常は大文字で書かれるのが慣例です。
print <<"END"; echo sample script END# echoコマンドが実行され、戻り値が文字列として保持されます。
[ CGI Top ]
[ BACK ]
[ Reference Top ]
[ NEXT ]
[ HOME ]