Perl,CGI - サンプル。
==================== Perl/CGI 基本 ==================== ■環境変数 ユーザエージェント $ENV{'HTTP_USER_AGENT'} リモートIPアドレス $ENV{'REMOTE_ADDR'} リモートホスト名 $ENV{'REMOTE_HOST'} 参照元URL $ENV{'HTTP_REFERER'} リクエストメソッド $ENV{'REQUEST_METHOD'} データの長さ $ENV{'CONTENT_LENGTH'} データのMIME $ENV{'CONTENT_TYPE'} エンコードデータ $ENV{'QUERY_STRING'} ■Content-type HTML Content-type: text/html HDML Content-type: text/x-hdml; charset=SHIFT_JIS GIF Content-type: image/gif JPEG Content-type: image/jpeg PNG Content-type: image/png BMP Content-type: image/bmp MPEG Content-type: video/mpeg WAVE Content-type: audio/x-wav PDF Content-type: application/pdf 一般的なバイナリ Content-type: application/octet-stream SMAF形式着信メロディ Content-type: application/x-smaf EZwebダウンロード形式 Content-type: application/x-up-download ■制御文 ・if if($i >= 1 && $i <= 5){ }elsif($i < 1 || ($i > 5 && $i < 10)){ }else{ } if($i == 1) if($i != 1) if($i eq 1) if($i ne 1) ・for for($i=0;$i<10;$i++){ } ・while while($i < 10){ $i++; } ・ループの最初に戻る next; ・ループを終了する last; ==================== Perl/CGI ページ・ファイル出力 ==================== ■ページ出力 #!/usr/bin/perl print "Content-type: text/html\n\n"; print "<HTML><BODY>サンプル</BODY></HTML>"; ■画像出力、データ出力 ・HTMLサンプル <IMG SRC="./cgi/imgview.cgi?param=50"> ・CGIサンプル #!/usr/bin/perl $buffer = $ENV{'QUERY_STRING'}; @pairs=split(/&/,$buffer); foreach $pair (@pairs){ ($name,$value) = split(/=/,$pair); $value =~ tr/+/ /; $value =~ s/%(..)/pack("C",hex($1))/eg; $cgi{$name} = $value; } $param = $cgi{'param'}; $imagefile = "img/image" . $param . ".gif"; $filesize = -s $imagefile; print "Content-type: image/gif\n"; print "Content-Length: $filesize\n\n"; open(DATA,"$imagefile"); print <DATA>; close(DATA); exit; ■出力 ・ソース内で出力 print "文字"; ・まとめて出力(ヒアドキュメント) print <<EOD; <html> <body> 表示 </body> <html> EOD ■ファイル ・読み書き open(FILE,"$filename");#読み込み open(FILE,"<$filename");#読み込み open(FILE,">$filename");#書き込み(上書き) open(FILE,">>$filename");#書き込み(追加書き込み) close(FILE);#閉じる ・ファイルサイズ $filename = "./data/test1.txt"; $filesize = -s $filename; ・サンプル1 #!/usr/bin/perl $filename = "./data/test.txt"; open(DATA, "<$filename"); while($filedata = <DATA>){ @splitdata = split(/\t/, $filedata); print "$splitdata[0]\t$splitdata[1]\n"; } close(DATA); exit; ・サンプル2 #!/usr/bin/perl $filename1 = "./data/test1.txt"; $filename2 = "./data/test2.txt"; open(FILE1, "<$filename1"); open(FILE2, ">>$filename2"); while($filedata = <FILE1>){ @splitdata = split(/\t/, $filedata); print FILE2 "$splitdata[3]\t$splitdata[0]\n"; } close(FILE2); close(FILE1); exit; ■ディレクトリ opendir(DIRH, "./$dirname");#開く readdir(DIRH);#読み取る closedir(DIRH);#閉じる ・サンプル #!/usr/bin/perl $dirname = "./"; $filename = ""; print "Content-type: text/html\n\n"; print "<HTML><BODY>"; opendir(DIRH, "./$dirname"); while($filename = readdir(DIRH)){ if($filename eq "." || $filename eq ".."){ next; } print "<A HREF=$filename>$filename</A><BR>\n"; } closedir(DIRH); print "</BODY></HTML>"; exit; ==================== Perl/CGI 文字列 ==================== ■文字列連結 ・連結 $str3 = $str1 . " : " . $str2; $str4 = "$str1 : $str2"; ・追加で連結 $str5 .= $str1; $str5 .= $str2; $str5 .= $str3; $str5 .= $str4; ■文字列分割 ・文字列の先頭0(1,2,・・・)後ろが-1(-2,-3,・・・) $str = substr($str, 取り出し開始位置, 取り出す長さ); $str = substr($str, 5); $str = substr($str, 5, 2); $str = substr($str, 5, -1); ■文字列検索 ・前方から検索 index(対象文字列, 検索文字列, 先頭0として検索開始位置) ・後方から検索 rindex(対象文字列, 検索文字列, 末尾0として検索開始位置) ・サンプル $str = "ABCDEFG"; $a = index($str, "E", 2); $c = rindex($str, "B", 6); ■文字列のサイズ(バイト数) $str = "ABCDEFG"; $b = length $str; ■パターンマッチ $ENV{'HTTP_USER_AGENT'} =~ /Windows/;#一致 $ENV{'HTTP_USER_AGENT'} !~ /Windows/;#不一致 ・複数の場合は|で区切る $ENV{'HTTP_USER_AGENT'} =~ /Windows|Mac/; ・サンプル #!/usr/bin/perl $userAgent = $ENV{'HTTP_USER_AGENT'}; print "Content-type: text/html\n\n"; print "<HTML><BODY>"; if($userAgent =~ /Windows/){ print "Windows<BR>"; }else{ print "Windows以外<BR>"; } print $userAgent; print "</BODY></HTML>"; exit; ==================== Perl/CGI 正規表現・一致・置換 ==================== ■正規表現の修飾子 ・修飾子 g:一致するものを全て探す o:1回だけ一致するものを探す i:大文字小文字の区別なし s:文字列を1行とみなす m:文字列を複数行とみなす e:文字列を式とみなす x:拡張正規表現(空白が無効) ・メタ文字 .:任意の1文字 *:直前パターン0回以上繰り返し +:直前パターン1回以上繰り返し ?:直前パターン0または1回以上繰り返し ^:文字列の先頭([]内で使った場合、~以外になる) $:文字列の最後 \:エスケープ(/などをエスケープするときに使う) |:論理輪 \d:数字。[0-9] \D:数字以外。[^0-9] \w:英数字。[_a-zA-Z0-9] \W:英数字以外。[^_a-zA-Z0-9] \s:空白。[ \t\n\r\f] \S:空白以外。[^ \t\n\r\f] \A:文字列の先頭。^と同じ。 \Z:文字列の最後。$と同じ。または\z。 -:[]内で範囲を示す。 ■正規表現 ^は、文字列の先頭 $は、文字列の最後 +は、1回以上の繰り返し メールアドレスチェック $filedata = "oshima\@sample.com"; if($filedata =~ /^[0-9,a-z,A-Z][0-9,a-z,A-Z,_,\.,-]+@[0-9,a-z,A-Z][0-9,a-z,A-Z,_,\.,-]+\.[a-z,A-Z]+$/){ #一致 }else{ #不一致 } ・URL:^http://[0-9,a-z,A-Z,_,\.,/,:,~,-]+$ ・半角数字:^[0-9]+$ ・電話番号:^[0-9][0-9,-]+[0-9]$ ・URLを取り出す(URLを判別してリンクを張る) $filedata =~ s/(https?:\/\/[-\w.!~*'" ();\/?:@&=+\$,%\#]+)/<A TARGET="_blank" HREF="$1">$1<\/A>/ig; ・メールアドレスを取り出す(メールアドレスを判別してリンクを張る) $filedata =~ s/([\w\.\-]+\@[\w\-]+\.[\w\.\-]+)/<A HREF="mailto:$1">$1<\/A>/ig; ・HTMLタグを除去する ^は、[]内で使うと~以外。 [^>]だと>以外の全ての文字 $filedata =~ s/<[^>]*>//gs; ・大文字を小文字にする $filedata =~ tr/A-Z/a-z/; ・小文字を大文字にする $filedata =~ tr/a-z/A-Z/; ■置換、変換 $data =~ s/置換したい文字(正規表現可)/置換後の文字/g; $data =~ s/変換対象のリスト/変換後の文字リスト/g; ・HTMLタグの回避 $data =~ s/&/&/g; $data =~ s/</</g; $data =~ s/>/>/g; ・5C(\)を含む文字の処理(表ソ十構能予申噂暴などの文字化け対策) $data =~ s/\\/\\\\/g; ファイル、フォーム、DBなどソース外部から取得した文字列のみ変換できる。 表示→表\示など ソース内の文字は、実行と同時に化けてしまう(\がエスケープ処理される) 5Cがたくさんある例文 十月発売予定の暴走レースゲームソフトの表示性能は、結構すごいという噂なので、ネットで申し込んだ。 ・SQLでエラーになりそうな文字 $data =~ s/\'/\\'/g; $data =~ s/,/\,/g; $data =~ s/\(/\\(/g; $data =~ s/\)/\\)/g; $data =~ s/\;/\\;/g; ・改行コードを<BR>に変換 $data =~ s/\r\n/<BR>/g; $data =~ s/\r/<BR>/g; $data =~ s/\n/<BR>/g; または $data =~ s/\015\012/<BR>/g; $data =~ s/\015/<BR>/g; $data =~ s/\012/<BR>/g; ・大文字を小文字にする $filedata =~ tr/A-Z/a-z/; ・小文字を大文字にする $filedata =~ tr/a-z/A-Z/; ==================== Perl/CGI 配列・ハッシュ ==================== ■配列 @str = ("AB","CDE","F","G","HIJK"); ・配列数取得 $i = $#str; ・サンプル @str = ("AB","CDE","F","G","HIJK"); for($i=0;$i<=$#str;$i++){ $strtotal .= $str[$i]; } print "$strtotal\n"; ・2次元配列、多次元配列 @list = (["a", "あ"], ["b", "い"], ["c", "う"], ["d", "え"], ["e", "お"]); for($i=0;$i<=$#list;$i++){ print $list[$i][0] . " : " . $list[$i][1]; } ■連想配列(ハッシュ) ・サンプル %list = ("a" => "1", "b" => "2", "c" => "3", "d" => "4", "e" => "5"); while(($key, $value) = each %list){ print $key . " : " . $value; } #連想配列のkeyとvalueを取り出す #この場合、連想配列に書いた順には表示されない #上記の2次元配列か以下のサンプルを使えば順番に表示される ・ハッシュのキーでソートして表示する場合 foreach $key (sort keys %list){ $value = $list{$key}; print $key . " : " . $value; } ・ハッシュのvalueの値が大きい方から逆順ソートする場合 #reverseがなければ昇順、あれば降順 foreach $key (reverse sort {$list{$a} <=> $list{$b}} keys %list){ $value = $list{$key}; print $key . " : " . $value; } ■スプリット(配列に分割) @splitdata = split(/分割の基準の文字/,$filedata); @splitdata = split(/\t/,$filedata); @splitdata = split(/,/,$filedata); ■語尾切り取り ・文字列の最後の文字を切り取る chop $str; ・文字列の最後の改行コードを切り取る chomp $str; ==================== Perl/CGI 日付 ==================== ■日付・曜日取得、閏年、月末日計算 #曜日 @wday_array = ('<FONT COLOR="#FF0000">[日]</FONT>','[月]','[火]','[水]','[木]','[金]','[土]'); #日付の取得 #戻り値:年月日時分秒曜日 sub GetDate{ ($sec, $min, $hour, $mday, $month, $year, $wday) = localtime; $wday = $wday_array[$wday]; $month ++; $year = $year + 1900; my $ymm = sprintf("%02d/%02d/%02d", $year, $month, $mday); my $hms = sprintf("%02d:%02d:%02d", $hour, $min, $sec); return "$ymm $hms $wday"; } #曜日の取得 #年月日を渡す #戻り値:曜日 sub GetWday{ my $wday_num; my($year, $month, $day) = @_; if($month == 1 || $month == 2){ $year --; $month += 12; } $wday_num = int($year + int($year / 4) - int($year / 100) + int($year / 400) + int((13 * $month + 8) / 5) + $day) % 7; return $wday_array[$wday_num]; } #月末日計算 #年月を渡す #戻り値:末尾の日数 sub GetLastDay{ my($month, $year) = @_; my @last_day_array = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); if($month < 1 || $month > 12){ $month = (localtime)[4] + 1; } if($year == 0){ $year = 1900 + (localtime)[5]; } if($month == 2 && GetLeapYear($year)){ return 29; }else{ return $last_day_array[$month - 1]; } } #閏年取得 #戻り値:閏年なら1、偽なら空 sub GetLeapYear{ my $year = shift; return ((($year % 4 == 0) && ($year % 100 != 0) || ($year % 400 == 0)) ? 1 : ''); } ==================== Perl/CGI メール送信 ==================== ■メール送信 / sendmail / メールヘッダ情報 #jcode.plのパス require "./jcode.pl"; #sendmailのパス $mail_path = '/usr/sbin/sendmail'; #管理者情報 #宛先のメールアドレス $mail_to = 'mailto@sample.jp'; #メールのタイトル $mail_subject = 'ご意見・ご質問'; #送信先のメールアドレスが存在しなかった場合の返送先 $mail_return_path = 'yahoo@yahoo.co.jp'; #本文 $mail_body = 'テスト'; #送信者のメールアドレス $mail_from = 'mailfrom@sample.com'; #JISに変換 jcode::convert(\$mail_subject, 'jis'); jcode::convert(\$mail_body, 'jis'); #メール送信 #-tは、メールのToヘッダを宛先とみなすオプション。 #通常sendmailコマンドは、宛先も同時に指定する必要がある。「sendmail test@sample.com」など。 #-iは、メール本文中に「.(ピリオド)」だけの行があってもメールの終端とみなさないオプション。 #smtpでは、ピリオドだけの行はメールの終端を意味するため、それを回避する。 #-fは、エラーメールの宛先(Return-Pathヘッダ)を付加するオプション。 if($mail_return_path ne ""){ open(MAIL, "| $mail_path -t -i -f $mail_return_path") or &Disp_Error; }else{ open(MAIL, "| $mail_path -t -i") or &Disp_Error; } #print MAIL "X-Mailer: Mailer\n"; #print MAIL "Reply-To: $mail_from\n"; #print MAIL "From: $mail_subject <$mail_from>\n"; print MAIL "From: $mail_from\n"; print MAIL "To: $mail_to\n"; print MAIL "Subject: $mail_subject\n"; print MAIL "MIME-Version: 1.0\n"; print MAIL "Content-type: text/plain; charset=ISO-2022-JP\n"; print MAIL "Content-Transfer-Encoding: 7bit\n"; print MAIL "\n"; print MAIL "$mail_body\n"; print MAIL "\n"; close(MAIL); print "Content-type: text/html\n\n"; print "送信しました。"; #エラー表示 sub Disp_Error{ print "Content-type: text/html\n\n"; print "メール送信エラー"; } ==================== Perl/CGI その他 ==================== ■サブルーチン ・サンプル #!/usr/bin/perl $i = 0; &count; exit; sub count{ for($i=0;$i<1000;$i++){ print "$i\n"; } } ■Location ・サンプル #!/usr/bin/perl $filename = "image.gif"; print "Location: http://example.com/cgi/$filename\n\n"; exit; ■URLエンコード $url = "あいうえお"; $url_enc = $url; $url_dec = ""; #type1 #エンコード #$url_enc =~ s/(\W)/'%' . unpack('H2', $1)/eg; #デコード #$url_dec = $url_enc; #$url_dec =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg; #type2 #エンコード $url_enc =~ s/([^\w ])/'%'.unpack('H2', $1)/eg; $url_enc =~ tr/ /+/; #デコード $url_dec = $url_enc; $url_dec =~ tr/+/ /; $url_dec =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg; #type3 #デコード #$url_dec =~ s/%(..)/pack("C", hex($1))/eg; print $url . "\n"; print $url_enc . "\n"; print $url_dec . "\n"; ■Base64 ・サンプル #!/usr/bin/perl use MIME::Base64; $string = "oshima"; $encoded = encode_base64($string,''); $decoded = decode_base64($encoded); print "元の文字 : $string\n"; print "Base64エンコード後 : $encoded\n"; print "Base64デコード後 : $decoded\n"; exit; ■日本語処理 jcode.pl ・最新版 ftp://ftp.iij.ad.jp/pub/IIJ/dist/utashiro/perl/ ・書き方(\マーク忘れに注意) &jcode'convert(*value,'sjis');#Perl4タイプ jcode::convert(\$data,'sjis');#Perl5タイプ ・SJISにする(元の文字は自動判定) jcode::convert(\$data,'sjis'); ・EUCからSJISにする(逆ならコード指定を入れ替える) jcode::convert(\$data,'sjis','euc'); ・全角半角変換 jcode::z2h_euc(\$data); #全角カタカナを半角カタカナに(EUC) jcode::h2z_euc(\$data); #半角カタカナを全角カタカナに(EUC) jcode::z2h_sjis(\$data);#全角カタカナを半角カタカナに(SJIS) jcode::h2z_sjis(\$data);#半角カタカナを全角カタカナに(SJIS) ・置換 jcode::tr(\$data,'0-9A-za-z','0-9A-za-z');#全角英数を半角英数に jcode::tr(\$data,'!$%&','!$%&');#全角記号を半角記号に ・フォームからの日本語をSJISにする #!/usr/bin/perl #jcode.pl require "./jcode.pl"; #POSTやGETを大文字に統一 $ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/; #フォームの内容を受け取る if($ENV{'REQUEST_METHOD'} eq "POST"){ #POSTの場合 read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }else{ #GETの場合 $buffer = $ENV{'QUERY_STRING'}; } @pairs = split(/&/, $buffer); foreach $pair(@pairs){ ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%(..)/pack("C", hex($1))/eg; jcode::convert(\$value, 'sjis'); $cgi{$name} = $value; } $text = $cgi{'text'}; ■フォームデータ、リンク引数取得(POST、GET)サンプル #!/usr/bin/perl #jcode.pl #require "./jcode.pl"; #POSTやGETを大文字に統一 $ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/; #フォームの内容を受け取る if($ENV{'REQUEST_METHOD'} eq "POST"){ #POSTの場合 read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }else{ #GETの場合 $buffer = $ENV{'QUERY_STRING'}; } @pairs = split(/&/, $buffer); foreach $pair (@pairs){ ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%(..)/pack("C", hex($1))/eg; # jcode::convert(\$value, 'sjis'); $cgi{$name} = $value; } $textbox = $cgi{'textbox'}; $textarea = $cgi{'textarea'}; $radio = $cgi{'radio'}; $select = $cgi{'select'}; $check[0] = $cgi{'check0'}; $check[1] = $cgi{'check1'}; ■引数処理 cgi-lib.pl ・最新版 http://cgi-lib.berkeley.edu/ ・サンプル require "./cgi-lib.pl"; &ReadParse(*cgi); $name = $cgi{'name'}; $mail = $cgi{'mail'}; ■引数処理 CGI.pm ・サンプル use CGI; $cgi = new CGI; $name = $cgi->param('name'); $mail = $cgi->param('mail'); ■システムコマンド実行 ・コマンド実行 system("javac -classpath $SRC_ROOT\;$SERVLET_JAR $SRC_FILE"); ・パイプ利用 open(FP, "| javac -classpath $SRC_ROOT\;$SERVLET_JAR $SRC_FILE"); close(FP); ■ライブラリ、モジュール利用 ・ライブラリ CGI側 require "./sample1.pl"; require "./sample2.pl"; &Get_Date; &Time::Get_Time sample1.pl $i = 0; sub Get_Date{ } 1; sample2.pl package Time; sub Get_Time{ } 1; ・モジュール CGI側 use CGI; $cgi = new CGI; $name = $cgi->param('name'); $mail = $cgi->param('mail');