• ベストアンサー

Perlの書き方

$addr = $ENV{'REMOTE_ADDR'}; open(IN,"$log"); my @data = <DATA>; foreach(@data){ my($ip)=split(/\,/,$_); if($ip==$addr){$a=1;} if ($a !=1) { 処理1 } else { 処理2 } } close(DATA); $logに$addrが含まれている場合は処理2を実行させたいと↑のスクリプトを書いてみました。私の環境(パソコンの環境と、設置サーバーの環境)では正常に動いているようですが、人に(パソコンの環境と、設置サーバーの環境)よっては、処理1が実行されてしまうようです。書き方は、これで間違っていませんでしょうか? もし間違っていないのでしたら、環境によって$logに$ipが記録されていないのかも知れません。perlの知識はあまりありませんが、よろしくお願いいたします。

  • Perl
  • 回答数3
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

・open が成功したかチェックしていない ・open(IN,"$log"); の $logを囲むダブルクォートは不要 ・open でオープンしているのがINなのに、配列に読み込んでいるのはDATAから ・split(/\,/,$_); ',' は特殊な文字ではないのでエスケープ不要 ・if($ip==$addr){$a=1;} $ip、$addrにはIPアドレスを表す「文字列」 が入っているので、== による比較を指定はいけない。 また、$a, $bという名前の変数は使うべきでない #!/usr/bin/perl use strict; use warnings; my $addr = $ENV{REMOTE_ADDR} || "192.168.1.1"; my $log = 'accesslog.dat'; open my $in, $log or die $!; my @data = <$in>; close $in; foreach my $line (@data) { my ($ip) = split q{,}, $line; if ($ip eq $addr) { print "$addr が見つかった\n"; } else { print "$addr ではなかった($ip)\n"; } }

yasainet
質問者

お礼

ありがとうございます。大変勉強になりました。

その他の回答 (2)

  • g_p_
  • ベストアンサー率53% (28/52)
回答No.3

>$found = 1 if /^$addr/; なんですけど、明らかにまずいですね、あんまり深く考えていませんでした。すみません。 せめて $found = 1 if /^${addr},/; なら、何とか使えますかね。 my($ip) = split /,/; if ( $ip eq $addr ) { $found = 1; } の方がいいかな? >last if$found;は、$foundを全て読み終わったらループを終了させるという意味でよろしいでしょうか? $found は単に、結果がどうだったか保存しておく変数です。勝手に書きました。 last ってのは、一番内側のループを終了させる時に使います。 一番内側でないループを抜けるなら、ラベルが必要です。 last if ~ ; はいわゆる慣用句ってヤツですかね。結構良く見る気がします。 ~ が真なら、ループを終了って感じです。 Perl は if ( 条件 ) { 処理 } を 処理 if 条件; て書いても同じなんで、そう書いた方が見易い場合(好み?)にそう書きます。

yasainet
質問者

お礼

有難うございました。今まではローカルでテストして問題なければ大丈夫だと心配していませんでしたが、サーバーに迷惑をかけては大変ですので、ループの終了方法に関してはしっかり勉強してみます。

  • g_p_
  • ベストアンサー率53% (28/52)
回答No.2

sakusaker7 さんの指摘以外で気になったので… >$logに$addrが含まれている場合は処理2を実行させたいと 1行ずつテストしたいなら、$a はループの最初で初期化しないとアレだし、 ファイル全体であるかないかなら、見つかった時点でループを終わるようにした方が いいんじゃないですかね? sakusaker7 さんのスクリプト借りてループを終わる例です。 #!/usr/bin/perl use strict; use warnings; my $addr = $ENV{REMOTE_ADDR} || "192.168.1.1"; my $log = 'accesslog.dat'; open my $in , '<' , $log or die $!; my $found; while (<$in>) { $found = 1 if /^$addr/; last if $found; } close $in; if ( $found ) { print "あった\n"; } else { print "なかった\n"; }

yasainet
質問者

お礼

ありがとうございます。大変勉強になりました。 last if$found;は、$foundを全て読み終わったらループを終了させるという意味でよろしいでしょうか?

関連するQ&A

  • [perl・php]gethostbyaddrは重い?

    今まで、REMOTE_ADDRを取得してアクセスログに記録していたのですが、最近、下記の存在を知りました。 $host = gethostbyaddr(pack("C4", split(/\./, $ENV{'REMOTE_ADDR'})), 2); ただ、これで、多大な負荷がかかるようならやめようと思うのですが、どの程度の負荷になるのでしょうか? ご存知の方、回答、宜しくお願い致します。

    • ベストアンサー
    • Perl
  • ページのアドレスを取得する記述方法を教えてください。

    たとえば、IP、HOSTを取得するには、 $host = $ENV{'REMOTE_HOST'}; $addr = $ENV{'REMOTE_ADDR'}; if(!$host && $addr){ $host = (gethostbyaddr(pack("C4",split(/\./,$addr)),2))[0]; } と記述して、 センドメール部分に、 $host , $addrをどこかに記述します。 これと同じように、ページのアドレスを取得する記述はどうすればいいのか教えてください。

    • 締切済み
    • CGI
  • IP/ホスト連続投稿チェック機能が上手く行かない。

    なんでだろ?? ###+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ## SUB >>> ホスト取得処理 ###+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ sub get_HostAgent { $Host = $ENV{'REMOTE_HOST'}; $Addr = $ENV{'REMOTE_ADDR'}; if ($Host eq '') { $Host = $Addr; } if ($Host eq $Addr) { $Host = gethostbyaddr(pack('C4',split(/\./,$Host)),2) || $Addr; } $H_A = "$Host"; } ホスト取得ルーチンにある変数で、 いろんな掲示板の中のP/ホスト連続投稿チェック機能だけ抜き出して、 もう何十個も試したけれど、上手くいきません。 カスタマイズしてる会員掲示板に、 IP/ホスト連続投稿チェック機能を付けたいのですが上手くいきません。 二重投稿チェックはあるのですが、、 ↓↓↓ #--二重投稿チェック--# if ($r1 eq "$name" && $r4 eq "$street<>$title" && $r5 eq "$comment") { &lock2; &error("二重投稿は禁止です"); } より極めるために、以下を利用したいのです。。 ↓↓↓ #--IP/ホスト連続投稿チェック--# if ($Addr = $ENV{'REMOTE_ADDR'} && $^T - $time < 120) { &lock2; &error("連続投稿はできません。<BR>時間をおいてから書き込みして下さい");} 宜しくお願い致します。 どこがおかしいのかサッパリです。 なんとか機能を追加できるようにお願いしますろ

    • 締切済み
    • CGI
  • 【 REMOTE_HOSTの値の取得方法について 】

    既製のCGIを設置するのがイッパイイッパイの 初心者ですm(__)m REMOTE_HOSTの値を取得して表示させたいのですが 当方レンタル中のサーバーの初期設定では取得できず 下記の如くの手順で取得するように表示してありましたが どうにも理解できず困っております。 下記の「Perl内」とは何処の事を指しているのか アドバイスを頂きたくお願い申し上げます。 ****以下、該当サーバーの説明文引用***** 【 REMOTE_HOSTの値の取得方法について 】 レンタルサーバーの処理速度を優先して、初期状態ではIPアドレスからDNSの参照をしないように設定している為、REMOTE_HOSTの値を取得したい場合はPerl内で下記の記述をして下さい。 $addr = $ENV{'REMOTE_ADDR'}; $host = gethostbyaddr(pack('C4',split(/\./,$addr)),2) || $addr;

    • ベストアンサー
    • Perl
  • Perlの日付取得で月の表示がおかしい

    下記は、メールフォームCGIに書き込まれた日時などの情報をlog.cgiというファイルに書き出すスクリプトです。 2012/01/04 21:05:45 のような感じで、日付が刻まれるのですが、このうち月の部分がどの月に処理を行ってもいつも01になってしまうのですが、当方直し方がわかりません。 下記が実際の記載箇所です。4行目がおかしいのだと思いますが、どなたかお分かりの方、教えていただけないでしょうか。 my $path = "log.cgi"; my $ip = $ENV{'REMOTE_ADDR'}; ($sec, $min, $hour, $mday, $month, $year, $wday, $stime) = localtime(time()); my $time = sprintf("%04d\/%02d\/%02d %02d\:%02d:%02d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec); my $message = $in{'メッセージ'}; $message =~ s/\r\n/ /g; $message =~ s/\n/ /g; if (open(FOUT, ">> $path")) { print FOUT "$time\t$ip\t" . $in{'お名前'} . "\t" . $in{'E-mail'} . "\t" . $message . "\r\n"; close(FOUT); } よろしくおねがいいたします。

    • ベストアンサー
    • Perl
  • cgi環境変数の変更方法?

    cgi環境変数の変更方法? perlで書かれたcgiプログラムがあります。 そのcgiではcgi環境変数内のREMOTE_ADDRを読出し、特定のIPアドレス【特定の端末】であれば特別処理を行っております。 今回、別の端末【別のIPアドレス】から同じ特別処理をする必要が生じました。 サーバ側のcgiプログラムを修正すれば簡単なのですが、著作権上の問題があって出来ません。 そこで端末側のプログラムがC#のWebClientクラスを使用してサーバと交信しているのを幸いとして myClient.Headers.Set("REMOTE_ADDR", "xxx,xxx,xxx,xxx"); ← 従前のIPアドレスへの変更 のステートメントを追加して強制的にIPアドレスを変更しようとしました。 ところがサーバ側のcgi環境変数には、HTTP_REMOTE_ADDRという新しい要素が加わっただけであり、目的とするREMOTE_ADDRを修正出来ません。 調べてみると、apacheがHTTP_タグを追加しているとのことです。 この追加をやめさせREMOTE_ADDRに当方が望むIPアドレスを設定することは可能でしょうか?

  • PerlからPHPに移植したアクセス制限

    下記は、CGIファイルから持ってきたスクリプトをPHPに変換してみたものです。 エラーが出るの出ます-> Parse error: syntax error, unexpected '/', expecting ')' in /home/users/1/raindrop.jp-5247423/web/tsukushinbo/bbs/bbs_header.php on line 32 どう修正すれば教えていただきたいです。 <?php #----------------# # ホスト名取得 # #----------------# function get_host(){ $host = $_SERVER{'REMOTE_HOST'}; $addr = $_SERVER{'REMOTE_ADDR'}; if($gethostbyaddr){ if ($host === "" || $host === "$addr") { $host === gethostbyaddr(pack("C4", split(/\./, $addr)), 2); $host === gethostbyaddr(pack($addr)); } } if($host === "") { $host = $addr; } } ?>

    • ベストアンサー
    • PHP
  • CGIの時間の環境変数

    ちょっとタイトルがあっているのか、イマイチ心配なのですが(汗) フォームのCGIを作っています。 登録情報がメールで届くようにしています。 ホスト名とかIPアドレス、ユーザーエージェントは下記でできました。 $host = gethostbyaddr(pack("C4", split(/\./, $ENV{'REMOTE_ADDR'})), 2); $addr = $ENV{'REMOTE_ADDR'}; $HTTP_USER_AGENT = $ENV{'HTTP_USER_AGENT'}; フォームに登録してくれた曜日とか時間を取るやり方がわかりません。 どなたかお知恵をお貸しください m(__)m

  • QUERY_STRING が、SSIを使用すると取得できません

    以下の2ファイルを使用して、 環境変数QUERY_STRINGの取得のテストをしています。 ------------------------------------------------ ファイル名:test_env.cgi ------------------------------------------------ 内容: print <<"HERE"; $ENV{'QUERY_STRING'}<br> $ENV{'REMOTE_ADDR'} HERE ------------------------------------------------ ------------------------------------------------ ファイル名:test_env.shtml ------------------------------------------------ 内容: <html> <head> <title> 環境変数のテスト </title> </head> <body> <!--#include virtual="/cgi-esp/test_env.cgi"--> </body> </html> ------------------------------------------------ ブラウザのアドレスバーに test_env.cgi?name=aaa と入力して実行すると、 QUERY_STRING、REMOTE_ADDR の両方が出力されますが、 test_env.shtml?name=aaa だと、 ローカルでは両方出力できたのに、 サーバにアップするとQUERY_STRINGが出力されません。 SSIを使用してCGIファイルを実行した場合、 QUERY_STRINGは取得できなくなるものなんでしょうか? それとも、取得できる書き方があるのでしょうか? どなたか、ご教示ください。

    • ベストアンサー
    • Perl
  • socket使用時の環境変数(REMOTE_ADDR)について

    色々調べても結局わかりませんでしたので もしお分かりになる方がいらっしゃれば 教えて頂ければ幸いです。 socketを使用するAというプログラムを作ったのですが、 そのプログラムからBというプログラムを呼び出した時、 Aに取得されるREMOTE_ADDRは、私のREMOTE_ADDRになるのですが、 Bに取得されるREMOTE_ADDRは、サーバのREMOTE_ADDRになってしまいます。 Bに対しても私のREMOTE_ADDRを取得させたいのですが、 方法はありますでしょうか? 具体的なSOCKET使用機構は以下のようになっております。 use IO::Socket qw(:DEFAULT :crlf); $/ = CRLF . CRLF; my $data; my ($host,$path) = $url =~m!^http://([^/]+)(/[^\#]*)!; my $socket = IO::Socket::INET->new(PeerAddr => $host, PeerPort => 'http(80)', Proto => 'tcp'); select($socket); $|= 1; select (STDOUT); print $socket "POST $path HTTP/1.0",CRLF,CRLF; close($socket); どうぞ宜しくお願い致します。

    • ベストアンサー
    • Perl

専門家に質問してみよう