• ベストアンサー

if文中で@***(配列変数)って・・・。

if文中で配列変数って使用できるのでしょうか? やりたいことは、 フォームを使って入力されたデータと、ログファイルの中身を1行ずつ比べて、 同じものがあったら、そこで比較を終了させる、というようなことをやりたいのです。 たとえでこんな感じでif文つくりました。(これもあってるかどうか微妙なのですが。) for($i=0; $i<5){ @FILELOG2 = split(/&/,$FILELOG[$i]); if (@FILELOG2 eq @log){ print "ok\n"; }else{ print "ng\n"; } exit; } フォームを使って入力されたデータは、 read(STDIN,$buffer,$ENV{'content_length'}); $buffer =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; @log =split(/&/,$buffer); のような感じで処理してあります。 ログファイルは #ログファイルをオープン。 open FILE,"<02.log"; flock(FILE,2); @FILELOG=<FILE>; flock(FILE,8); close FILE; のようにしてあります。 おわかりの方、よろしくお願いします。

  • CGI
  • 回答数4
  • ありがとう数4

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

  • ベストアンサー
  • HUTABA
  • ベストアンサー率27% (436/1611)
回答No.3

#1です。 >FILELOG2の前の#は何を意味するものなのでしょうか? $#FILELOG2は、@FILELOG2の最後の添え字を返します。 例えば@FILELOG2の要素数が3だった場合は、2を返します。 >合っているところまでそれぞれの値を表示し、止まるのですが、 >「あってるよ」が表示されません。 >なぜでしょうか? 横レスで申し訳ありませんが、ログファイルの方には改行が含まれていませんか? 例えば $SYOZOKU1 が "所属" $SYOZOKU2 が "所属\n"の場合、表示すると一見同じに見えますが改行が入っているので if ($SYOZOKU1 eq $SYOZOKU2) はヒットしません。 $SYOZOKU2の改行をあらかじめ取っておくなりすれば良いと思いますよ。

KODAMAR
質問者

お礼

回答ありがとうございます。 >$#FILELOG2は、@FILELOG2の最後の添え字を返します。 ありがとうございます、理解できました。 >$SYOZOKU2の改行をあらかじめ取っておくなりすれば良いと思いますよ。 @FILELOG2 = split(/&/,$FILELOG[$i]); @FILELOG2 = ~ s/\n//g; のようにしてみましたが、やはりダメでした。 改行をとるというのはこういうことではないのでしょうか? よろしくお願いします。

その他の回答 (3)

  • HUTABA
  • ベストアンサー率27% (436/1611)
回答No.4

#1、#3です。 @FILELOG2 = ~ s/\n//g; ではなくて、 for文の中で $FILELOG[$i] =~ s/\n$//; @FILELOG2 = split(/&/,$FILELOG[$i]); として下さい。 \n$ の "$" は正規表現で文末を意味します。 この場合、文末の\nだけを削除します。

KODAMAR
質問者

お礼

回答ありがとうございます。 文末には「$」を使うんですね。 知りませんでした。 無事「あってるよ」が出力されました。 ありがとうございました。

KODAMAR
質問者

補足

また教えていただきたいのですが、 print "Content-type:text/html\n\n"; $flag = 0; for($i=0;$i<$#FILELOG && $flag==0;$i++){ $FILELOG[$i] =~ s/\n$//; @FILELOG2 = split(/&/,$FILELOG[$i]); ($BANGOU2,$NAME2,$SYOZOKU2) = split(/&/,$FILELOG[$i]); ($BANGOU2TITLE,$BANGOU2) = split(/=/,$BANGOU2); ($NAME2TITLE,$NAME2) = split(/=/,$NAME2); ($SYOZOKU2TITLE,$SYOZOKU2) = split(/=/,$SYOZOKU2); print "$flag$flag<BR>\n"; print "$i$i<BR>\n"; print "BANGOU1は「$BANGOU1」<BR>\n"; print "NAME2は「$NAME1」<BR>\n"; print "SYOZOKU1は「$SYOZOKU1」<BR>\n"; print "<BR>\n"; print "BANGOU2は「$BANGOU2」<BR>\n"; print "NAME2は「$NAME2」<BR>\n"; print "SYOZOKU2は「$SYOZOKU2」<BR>\n"; print "<BR><HR>\n"; if($BANGOU1 eq $BANGOU2 && $NAME1 eq $NAME2 && $SYOZOKU1 eq $SYOZOKU2){ print "あってるよ\n"; } #終わらせたい時は $flag を 1 にする } としていますが、ログファイルの2行目まで(iが1まで)しか動作しません。 なぜでしょうか?

  • duckling
  • ベストアンサー率47% (88/185)
回答No.2

> if (@FILELOG2 eq @log){ ↑これだと、両方の配列の数が同じだったらtrueが返ります。 if文で配列丸ごとゴッソリ 「中身がまったく同じだったら」という一発比較は、 どの言語であっても出来ないと思いますよ。 ($a,$b,$c) = split(/&/,$FILELOG[$i]); と、変数に格納してから if($a eq $log[0] && $b eq $log[1] && $c eq $log[2]){ print "OK"; } とした方がいいです。 > そこで比較を終了させる をやりたい場合は、 $flag = 0; for($i=0;$i<$#FILELOG && $flag==0;$i++){ #終わらせたい時は $flag を 1 にする } として、$flagが0の間だけfor回しを行う、 という風にしたらいいのではないでしょうか。

KODAMAR
質問者

お礼

回答ありがとうございます。 ご指摘とおり、こんな感じにしてみました。 #フォームで送られてきたデータを分割 ($BANGOU1・$NAME1・$SYOZOKU1) ($BANGOU1,$NAME1,$SYOZOKU1) =split(/&/,$buffer); ($NAKAMITITLE,$BANGOU1TITLE,$BANGOU1) = split(/=/,$BANGOU1); ($NAME1TITLE,$NAME1) = split(/=/,$NAME1); ($SYOZOKU1TITLE,$SYOZOKU1) = split(/=/,$SYOZOKU1); #ログファイルを分割 ($BANGOU2・$NAME2・$SYOZOKU2) ($BANGOU2,$NAME2,$SYOZOKU2) = split(/&/,$FILELOG[$i]); ($BANGOU2TITLE,$BANGOU2) = split(/=/,$BANGOU2); ($NAME2TITLE,$NAME2) = split(/=/,$NAME2); ($SYOZOKU2TITLE,$SYOZOKU2) = split(/=/,$SYOZOKU2); それをfor文でループさせる。 print "Content-type:text/html\n\n"; $flag = 0; for($i=0;$i<$#FILELOG && $flag==0;$i++){ @FILELOG2 = split(/&/,$FILELOG[$i]); ($BANGOU2,$NAME2,$SYOZOKU2) = split(/&/,$FILELOG[$i]); ($BANGOU2TITLE,$BANGOU2) = split(/=/,$BANGOU2); ($NAME2TITLE,$NAME2) = split(/=/,$NAME2); ($SYOZOKU2TITLE,$SYOZOKU2) = split(/=/,$SYOZOKU2); print "$BANGOU1<BR>\n"; print "$NAME1<BR>\n"; print "$SYOZOKU1<BR>\n"; print "<BR>\n"; print "$BANGOU2<BR>\n"; print "$NAME2<BR>\n"; print "$SYOZOKU2<BR>\n"; if($BANGOU1 eq $BANGOU2 && $NAME1 eq $NAME2 && $SYOZOKU1 eq $SYOZOKU2){ print "あってるよ\n"; } #終わらせたい時は $flag を 1 にする } としてみました。 合っているところまでそれぞれの値を表示し、止まるのですが、 「あってるよ」が表示されません。 なぜでしょうか? よろしくお願いします。

  • HUTABA
  • ベストアンサー率27% (436/1611)
回答No.1

>if (@FILELOG2 eq @log) このif文だと、KODAMARさんの期待通りの動作はしません。 この場合、@FILELOG2と@logの要素数を比較し、同じ数であればtrueを返します。 >フォームを使って入力されたデータと、ログファイルの中身を1行ずつ比べて、 >同じものがあったら、そこで比較を終了させる、というようなことをやりたいのです。 であれば、 for ($i=0; $i<=$#FILELOG2; $i++) {  if ($FILELOG2[$i] eq $log[$i])  {   print "OK";  }  else  {   print "NG";  } } と、素直にループを回した方が良いですよ。

KODAMAR
質問者

お礼

回答ありがとうございます。 このままコピーして貼り付けてみたのですが、エラーが返ってきてしまいました。 なぜでしょうか・・・? >for ($i=0; $i<=$#FILELOG2; $i++) FILELOG2の前の#は何を意味するものなのでしょうか? よろしくお願いします。

関連するQ&A

  • ログファイルと受信データを比べたい。

    フォームを使用して送られてきたデータをlogを比べて同じものがあったら、同じものがあるということを表示したいのです。 前にも同じようなことをしてできたはずなのですが、なぜかできなくて…。 もうずーっとやっていて頭がボーッとしてきてしまいました。。。。 #フォームで受信したデータ read(STDIN,$buffer,$ENV{'content_length'}); $buffer =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; #ログファイルオープン open FILE,"naisen.log"; @FILES =<FILE>; close FILE; $i=0; $n=0; $gyou = @FILES; #文末の改行を削除 $buffer =~ s/\n$//; $FILES[$i] =~ s/\n$//; foreach(@FILES){ @log = split(/&/,$FILES[$i]); ($keys,$values) = split(/=/,$log[$_]); $FORMS{$keys} = $values; } for ($i=0; $i<=$gyou-1;$i++){ if ($buffer eq $FILES[$i]){ print "$i行目<BR>\n"; } else{ print "$i行目。これはありません。<BR>\n"; print "$FILES[$i]<BR>\n"; print "$buffer<BR>\n"; } } ログの1行目と同じものとときだけ、きちんとした結果がでます。 上記のほかにもいろいろやりましたができませんでした。

    • ベストアンサー
    • CGI
  • 半角スペースが有効にならない。

    前のページで入力された値を取得するCGIですが、どうしても半角スペースを認識しません。 それどころか、半角スペースの後ろを一切消してデータを取得しています。 同じように作成したものはきちんと動いているのに…。 どこが間違ってるかご指摘お願いします。 ---------- #!/usr/local/bin/perl read(STDIN,$buffer,$ENV{'content_length'}); @atai = split(/&/,$buffer); foreach $atais(@atai){ ($key, $value) = split(/=/, $atais); $FORM{$key}=$value; } $buffer =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $key =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $buffer =~ tr/+/ /; $value =~ tr/+/ /; $key =~ tr/+/ /; print "Content-type:text/html\n\n"; print "$key<BR>\n"; print "<A HREF=./***.cgi>Back</A><BR>\n"; open (FH,">***.log"); @filew="$buffer\n"; print FH @filew; close(FH); exit; ---------- 以上です。よろしくお願いします。

    • ベストアンサー
    • CGI
  • if文を使用すると表示されません。

    フォームに年月日を入力してもらい、下記のスクリプトで 入力画面を表示させようとしています。 年月日を入力するフォームにはhiddenをいれ、if文でサブルーチン &newFormを表示させようとしているのですが、うまくいきません。 <input type=hidden name=mode value="data"> if文を使用せずに、&newFormを直接呼び込むと表示するのですが・・・。 ぜひご教授願えればと思います。 よろしくお願いします。 ===================================================================== &query; # 初期設定 if($in{'mode'} eq "date"){ &newForm; } sub newForm{ print"Content-type:text/html\n\n"; print <<EOF; <html> <head> <title></title> </head> <body> <textarea name="diary" rows="30" cols="70"></textarea><br> <input type="submit" value="書き込み"> </body> </html> EOF } sub query{ $ENV{'REQUEST_METHOD'}=~ tr/a-z/A-Z/; if ( $ENV{'REQUEST_METHOD'} eq "POST" ){ read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }else{ $buffer = $ENV{'QUERY_STRING'}; } @pairs = split(/&/,$buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $in{$name} = $value; } }

    • ベストアンサー
    • CGI
  • フォームで入力されたアドレスに内容のコピーを自動返信

    下記フォームのCGIに、フォームで入力したアドレスに内容のコピーを自動で返信したいと考えています。 htmlフォームのメールの項目は、name="mail"です。 $clength = $ENV{'CONTENT_LENGTH'}; if ($clength ne '') { read(STDIN, $query_string, $clength); @elements = split(/&/, $query_string); $i = 0; foreach $element (@elements) { ($key, $buf) = split(/=/, $element); $key =~ tr/+/ /; $key =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; &jcode'convert(*key, 'jis'); @name[$i] = $key; $buf =~ tr/+/ /; $buf =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; &jcode'convert(*buf, 'jis'); @value[$i] = $buf; $i++; } $mail = $FORM{'mail'}; &jcode'convert(*sname, 'jis'); &jcode'convert(*subject, 'jis'); &jcode'convert(*ftitle, 'jis'); open (MAIL, "| $sendmail -f $smail $trans"); if ($sname ne '') { print MAIL "From: \"$sname\" <$smail>\n"; } else { print MAIL "From: $smail\n"; } print MAIL "Content-Type: text/plain; charset=\"ISO-2022-JP\"\n"; print MAIL "Subject: $subject\n"; print MAIL "\n"; print MAIL "$ftitle\n"; print MAIL "\n"; $tmp = '送信内容'; &jcode'convert(*tmp, 'jis'); print MAIL "$tmp\n"; print MAIL "----------------------------------\n"; for($j = 0; $j < $i; $j++) { print MAIL $j+1 . ": @name[$j] => @value[$j]\n"; } print MAIL "------------------------------------\n"; close(MAIL); print "Location: $query_file\n\n"; }

    • 締切済み
    • CGI
  • utf-8環境で標準入力からの全角文字にマッチさせる方法

    utf-8でフォーム処理のコードを書いてます。 euc-jpで動作していた全角文字の正規表現がutf-8で動作しません。 単純な「$str =~ /あ/」のような書き方ではなく、別な指定方法が必要なのでしょうか? ・perl5.8 文字コードutf-8 標準入力側文字コードutf-8 use utf8; my(%POST,$buffer,$key,$value,@data_s); if ($ENV{'REQUEST_METHOD'} eq 'POST') { if ($ENV{'CONTENT_TYPE'} =~ /application\/x-www-form-urlencoded/i) { binmode STDIN; read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'}); @data_s = split(/&/,$buffer); foreach $buffer (@data_s) { ($key,$value) = split(/=/,$buffer); $value =~ tr/+/ /; $value =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("C",hex($1))/eg; if ( exists ($POST{$key}) ) { $POST{$key} .= '<>' . $value; } else { $POST{$key} = $value; } } } } binmode STDOUT,":encoding(utf8)"; print "Content-type: text/html; charset=utf-8\n\n"; print "<br>\n"; foreach $key (keys %POST) { if ($POST{$key} =~ /[0-9]/) { print "全角数字にマッチ<br>\n"; }###### print "$key = $POST{$key}<br>\n"; } exit;

    • ベストアンサー
    • Perl
  • cgiログファイルの書き込みに余計なスペースが入る。

    ---------- #ここでログファイルに書き込みを行う。 open(FH,">>log.log"); print FH"ID=$ID&COUNT=$COUNT\n"; close(FH); #ログファイルをさらに開く。 open FILE, "<log.log"; flock(FILE,2); @log = <FILE>; flock(FILE,8); close FILE; ログファイルを並び替えてその順番で書き込み。 $gyou = @log; @sort=sort{(split(/&/,$b))[1] cmp (split(/&/,$a))[1];} @log; print "<FONT COLOR=RED>@sort</FONT><BR>\n"; open(FILE2, ">log.log"); print FILE2"@sort"; close (FILE2); ---------- というように行っていますが、一番最初のID=01&とかの前に半角スペースが入ります。 下の行に行くほどスペースが増えます。 どこが原因でしょうか?

    • ベストアンサー
    • Perl
  • CGIでhtmlページを表示する

    連日質問させていただいています。 CGI超初心者です。 htmlファイルにラジオボタンを設置し、 Aを選んだらhttp://www.a.html、 それ以外を選んだらhttp://www.b.html というサイトを開くようなCGIを作成したいです。 以下のようにやってみたのですがうまくいきません。 どのように修正したらいいでしょうか? #============================================ if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $str, $ENV{'CONTENT_LENGTH'}); } else { $str = $ENV{'QUERY_STRING'}; } foreach $i (split('&', $str)) { $i =~ tr/+/ /; $i =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C", hex($1))/eg; ($t1, $t2) = split('=', $i); $FORM{"$t1"} = $t2; } $q1 = $FORM{'radio'}; print "Content-Type: text/html; charset=Shift_JIS\n\n"; print "<html>\n"; print "<head></head>\n"; print "<body>\n"; if ($q1 eq "A") { print "Location: http://www.a.html\n\n"; } else { print "Location: http://www.b.html\n\n"; } print "</body>\n"; print "</html>\n"; exit; #============================================ 上記のようにすると、以下のように、ただ文字が表示されてしまいます。 Location: http://www.a.html #============================================ if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $str, $ENV{'CONTENT_LENGTH'}); } else { $str = $ENV{'QUERY_STRING'}; } foreach $i (split('&', $str)) { $i =~ tr/+/ /; $i =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C", hex($1))/eg; ($t1, $t2) = split('=', $i); $FORM{"$t1"} = $t2; } $q1 = $FORM{'radio'}; print "charset=Shift_JIS\n\n";←★ print "<html>\n"; print "<head></head>\n"; print "<body>\n"; if ($q1 eq "A") { print "Location: http://www.a.html\n\n"; } else { print "Location: http://www.b.html\n\n"; } print "</body>\n"; print "</html>\n"; exit; #============================================ ★部分が悪いのかなぁと思い、上記のように修正してみたり、 (Content-Type: text/html; を削除してみました) ★部分を全部削除してみると Internal Server Error となってしまいます。 よろしくお願いいたします!

    • ベストアンサー
    • CGI
  • 受信データの分割

    @atai = split(/&/,$buffer); foreach $atais(@atai){ ($key, $value) = split(/=/, $atais); $FORM{$key}=$value; } 多分上記のようなことをすればできるのだと思うのですが、 自分の力でコードをかきたくて、1行ずつかいてみました。 #ファイルオープン open FILE,"<log.log"; flock(FILE,2); @log_data=<FILE>; flock(FILE,8); close FILE; foreach(@log_data){ (@log) = split(/=/,$_); } foreach(@log){ ($log_data) = split(/&/,$_); } foreach($log_data){ ($key,$value) = split(/=/,$_); } $FORM{$key}=$value; このようにかいてみたのですがうまくいきません。 よろしくお願いします。

    • ベストアンサー
    • CGI
  • Sendmailの文字化けについて

    以前にも同じ質問をしたのですが、いまいち解決していないので、もう一度質問させて頂きます。 ホームページでsendmailをつかってフォームより記入してもらった内容を自分のところと確認メールとして記入した人のところに送るようにしていますが、確認メールが文字化けすることがあるようです。 しかし、全ての人に対して化けるというわけではなく、ほとんどの場合は大丈夫なようですが、一部の人に対してだけ化けるようです。 関係しそうな部分を大まかに書くと下記のようにしておりますが、間違っているでしょうか? if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); } else { $buffer = $ENV{'QUERY_STRING'}; } @pairs = split(/&/,$buffer); foreach $pair (@pairs){ ($name, $value) = split(/=/, $pair); $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; &jcode'convert(*value,'sjis'); &jcode'convert(*name,'sjis'); $xx =$value; &trans; $value = $xx; } sub trans{ $from='[@01-9A-Za-z._-]'; $to='[@01-9A-Za-z._-]'; &jcode'convert(*xx, 'euc'); &jcode'convert(*from, 'euc'); &jcode'convert(*to, 'euc'); &jcode'tr(*xx, $from, $to); &jcode'convert(*xx, 'sjis'); } &jcode'convert(*message,'jis'); if (!open(MAIL,"|$sendmail $mail_address")) {&error;} &jis("Subject: $mailname"); print MAIL "$msg\n"; print MAIL "To: $mail_address\n"; print MAIL "From: $mailfrom\n"; print MAIL "\n"; print MAIL "$message"; close(MAIL); sub jis { $msg = $_[0]; &jcode'convert(*msg, 'jis');}

    • ベストアンサー
    • Perl
  • use constantの意味が分からない

    以下の use constant SMAX => 50;とuse constant CMAX => 10; を $SMAX = 50; $CMAX = 10; に変更し、if ( SMAX < $max ) { $n = $max - SMAX; }も if ( $SMAX < $max ) { $n = $max - $SMAX; } と変更しましたが、機能してませんでした。 どこが間違っておりますでしょうか? 宜しくお願いします。 以下がCGIです。 #!/usr/bin/perl # 保存するコメント数 use constant SMAX => 50; # 表示するコメント数 use constant CMAX => 10; #----------------------------- if ($ENV{'REQUEST_METHOD'} eq "POST"){ read (STDIN,$buffer,$ENV{'CONTENT_LENGTH'}); } if ($ENV{'REQUEST_METHOD'} eq "GET") { $buffer = $ENV{'QUERY_STRING'}; } @list = split (/&/,$buffer); foreach (@list){ ($key,$value) = split (/=/,$_); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/ pack ("C",hex($1))/eg; $getdata{ $key } = $value; } $x = $getdata{ 'px' }; $y = $getdata{ 'py' }; $comment = $getdata{ 'com' }; $file = 'comment.dat'; open (IN,"$file"); @list = <IN>; close (IN); chomp(@list); $max = @list; if ( $x != '' ){ $writedata = $x.'<>'.$y.'<>'.$comment; if ( SMAX < $max ) { $n = $max - SMAX; } else { $n = 0; } open (OUT,"> $file"); flock(OUT,2); for ( ; $n < $max; $n++ ) { print OUT $list[$n]."\n"; } print OUT $writedata; close (OUT); } if ( CMAX < $max ) { $n = $max - CMAX; } else { $n = 0; } print "Content-type: text/html\n\n"; for ( ; $n < $max; $n++ ) { print $list[$n]."\n"; } if ( $x != '' ){ print $writedata; } exit ;

    • ベストアンサー
    • Perl

専門家に質問してみよう