• ベストアンサー

データリストにデータが無い場合に追加する

db.logファイルにgooのデータが無い場合に追加するcgiを作ってみたのですが、下記の様にダブって登録されてしまうのですが、ダブらずに登録するようにするにはどの様にすれば良いのでしょうか? サーバーはUNIXでWindowsXPからdb.logファイルをサーバーに転送させました。 それと$Check_list !~ m/($bb)/でリストにあるかないかを判断してるのですが、他に良いチェック方法ないでしょうか? <CGIアクセス前のdb.logファイル> yahoo;http://www.yahoo.co.jp; google;http://http://www.google.co.jp; <CGIアクセス後のdb.logファイル> yahoo;http://www.yahoo.co.jp; google;http://http://www.google.co.jp;goo;http://www.goo.ne.jp; goo;http://www.goo.ne.jp; <CGIファイル> #!/usr/bin/perl print "Content-type: text/html\n\n"; print<<"end"; <HTML><BODY> end open(Check_DB," < db.log"); while ($_=<Check_DB>){ ($a,$b) = split(/;/,$_); $Check_list.= "$b"; } close(Check_DB); $aa="goo"; $bb="http://www.goo.ne.jp"; if ($Check_list !~ m/($bb)/){ open(ADD_DB,">>db.log"); print ADD_DB "$aa;$bb;\n"; close(ADD_DB); } open(Print_DB," < db.log"); while ($_=<Print_DB>){ ($a,$b) = split(/;/,$_); print " サイト名 :$a URL :$b<BR>"; } close(Print_DB); print "</BODY></HTML>";

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

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

  • ベストアンサー
  • Ethersky
  • ベストアンサー率71% (168/235)
回答No.3

> 判定の方ですが$Check_listが巨大になる可能性があります。その際のperl ver5で変数の最大文字数の制限ってあるのでしょうか? 動かしているマシンの性能(メモリの量)次第です。 節約したいならこんな書き方もできます。 $aa="goo"; $bb="http://www.goo.ne.jp"; open(DB, "< db.log"); open(TMP, "> tmp.log"); $flag = 1; while (<DB>){ $addr = (split(/;/))[1]; if($addr eq $bb){$flag = 0;} print TMP; } if($flag){print TMP "$aa;$bb;\n";} close(TMP); close(DB); unlink("db.log"); rename("tmp.log","db.log"); 標準出力への出力も同時にやるなら・・・ $aa="goo"; $bb="http://www.goo.ne.jp"; open(DB, "< db.log"); open(TMP, "> tmp.log"); $flag = 1; while (<DB>){ ($name,$addr) = split(/;/); if($addr eq $bb){$flag = 0;} print TMP; print " サイト名 :$name URL :$addr<br>"; } if($flag){ print TMP "$aa;$bb;\n"; print " サイト名 :$aa URL :$bb<br>"; } close(TMP); close(DB); unlink("db.log"); rename("tmp.log","db.log");

meikenpochi
質問者

お礼

Etherskyさん、回答ありがとうございます。 参考にさせていただきます。

その他の回答 (2)

  • hikomin
  • ベストアンサー率63% (40/63)
回答No.2

> 判定の方ですが$Check_listが巨大になる可能性があります。その際のperl ver5で変数の最大文字数の制限ってあるのでしょうか? 多分…ないんだと思います…。今まで、大きなテキストデータ・バイナリデータを全てメモリ(変数)に読み込むという処理はたくさん行ないましたが、今のところ壁にぶつかっていないです…。(すいません、考えた事もなかったです…。)

  • hikomin
  • ベストアンサー率63% (40/63)
回答No.1

ええと、この結果ですが、CGIに2回(以上)アクセスしていませんか?また、google;http://http://www.google.co.jp;のうしろに改行はありますか? 私の想像では、1回目のアクセスの際にgooのデータを追加するものの、 google;http://http://www.google.co.jp; の後に改行が無いため、そのまま繋がって google;http://http://www.google.co.jp;goo;http://www.goo.ne.jp;(改行) となり、2回目の実行時には google;http://http://www.google.co.jp;goo;http://www.goo.ne.jp; の行をsplitした時の$bは http://http://www.google.co.jp なので、gooのデータが判定されずもう一度追加されて yahoo;http://www.yahoo.co.jp; google;http://http://www.google.co.jp;goo;http://www.goo.ne.jp;(改行) goo;http://www.goo.ne.jp;(改行) となったのではないかな、と思うのですが。 原因が分かれば、対策法も考えられるのではないでしょうか。 なお、判定に関してですが、行を読みながらいちいち判定してフラグを立てたりする手も考えられそうです。($bの内容を毎回eq等で調べて、見つけたら$flag = 1;とかにしてループを終え、if($flag){};等で追加する、等。)ただ、Perlの場合はいろんな書き方が出来るので特に、状況によって何がベストなのかは変わってきます。その都度いろいろ考えてみるべきと思います。(毎回判定すると言う事は、if内の評価が数多く行われる。その点$Check_listに判定用データを加えていけば正規表現に頼るものの判定は1回で済むが、$Check_listが巨大になる可能性もある。とかとか。)

meikenpochi
質問者

お礼

hikominさん、早速の回答ありがとうございます。 ご指摘して頂いた通り、db.logを下記の様に改行を追加したら、出来ました。 <修正前> yahoo;http://www.yahoo.co.jp;(改行) google;http://http://www.google.co.jp; <修正後> yahoo;http://www.yahoo.co.jp;(改行) http://www.google.co.jp;(改行) 判定の方ですが$Check_listが巨大になる可能性があります。その際のperl ver5で変数の最大文字数の制限ってあるのでしょうか?

関連するQ&A

  • ファイルのロックについて

    ファイルのロック方法を下記の様にしてロックさせていますが、同時ににアクセスが合ったときにどちらかが$add_text;を書きこまれないので順次書き込まれる様にしたいのですが、何方かご教授してもらえませんか? #!/usr/bin/perl use Fcntl ':flock'; open(ADD_DB,">>$log"); flock(ADD_DB, LOCK_EX); print ADD_DB "$add_text;\n"; flock(ADD_DB, LOCK_NB); close(ADD_DB);

    • ベストアンサー
    • Perl
  • 同一のメールアドレスの禁止設定を追加したい

    同一のメールアドレスを禁止するのを掲示板に適用させたいのですが、男性のログと女性のログがあり、どう設定していいか分かりません。男女のログファイルは階下のフォルダに入ってて、 男性 $mensfile 女性 $ladysfile とメインのCGIで設定されていす。 チャレンジしてみたら、過去のログファイルが全て消えてしまい散々な目に会いました。下のどちらかでできそうな・・宜しくお願い致します。 (1)# 二重登録のチェックをします if(-e $data){ open(FILE, "< $data"); # この時点でファイルは必ず存在します while(<FILE>){ @v = split(/\t/); if(@v[0] eq $name){ print "<center><b>すでに$nameさんは登録されています</b><br>\n"; print "「戻る」を押して入力しなおしてください</center>\n"; exit(0); } } close(FILE); } (2)#----------2重登録チェック---------- &lock; if(!open(IN,"$mail01")) {print 'ファイルOPENができませんでした。',"\n"; exit;} @dataline = <IN>; close(IN); unlink $lockfile; foreach $DATA (@dataline) { chomp $DATA; if($DATA eq $MAIL){ print 'このメールアドレスは既に登録されています。',"\n"; exit; } 宜しくお願い致します。

    • ベストアンサー
    • CGI
  • ローカルだとうまくいかない。。

    ActivePerlやANHTTPD?を使用してローカルでcgiのテストをしようとしています。 普通のcgiファイルは表示されますが、ファイルオープンなどがうまくいきません。 ためしにそのままweb上にアップしたら、きちんとログファイルが表示されました。 open FILE,"<log.log"; flock(FILE,2); @log = <FILE>; flock(FILE,8); close FILE; $gyou = @log; print "ログファイル:@log<BR>\n"; こんなふうにしてあります。 なぜローカルだとファイルオープンができないのでしょうか?

    • ベストアンサー
    • Perl
  • Perlの初心者です。2重ループの方法で困ってます。

    ある二つのファイル(moto1.csvとmoto2.csv)の2番目のフィールドが おなじときに二つのファイルの中身をあわせて別のファイル(kekka.csv)を 作る作業をしています。 下記のソースで※2の場所で何回もファイルをオープンさせるととても重いので ※1でファイルを一回だけオープンさせて処理しようと思ったら。 内側のループ(moto2_Log)が一回しか処理されないので困っております。 何かよいアイデアがありましたらよろしくお願いします。 open(moto1_Log,"< moto1.csv"); open(kekka_Log,"> kekka.csv"); ※1open(moto2_Log,"< moto2.csv"); while( <moto1_Log> ) { chop; @moto1_List=split(/,/); ※2 #open(moto2_Log,"< moto2.csv"); while( <moto2_Log> ) { chop; @moto2_List=split(/,/); if($moto1_[1] eq $moto2_List[1]){ print kekka_Log $S_List[0]; print kekka_Log ","; print kekka_Log $S_List[1]; print Export_Log ","; print Export_Log $S_List[2]; print Export_Log ","; print Export_Log $S_List[3]; print Export_Log ":"; print Export_Log $E_List[0]; print Export_Log ","; print Export_Log $E_List[1]; print Export_Log ","; print Export_Log $E_List[2]; print Export_Log ","; print Export_Log $E_List[3]; print Export_Log "\n"; #改行コード continu; } } } close (moto2_Log); close(kekka_Log); close(moto1_Log);

    • ベストアンサー
    • Perl
  • リストにデータがあれば1回だけ表示…

    更新記録CGIを改造して新商品入荷情報CGIとして利用しています。 お客様からメールでの問い合わせを受けるときに"どの商品についてか"というのを明確にしたいと考えています。 さらにちょっと改造して、もしこのジャンルの商品があった場合は「商品ありますよ」を一番上に表示して下にリストを(商品リストを抜き出して<select>で表示させる方法はわかりました)、無ければ「今は無いですよ」だけを表示させたいです。 少ない知識で作ってみましたが、うまく出来ません。 open (FILE,"$data"); @file = <FILE>; close FILE; foreach $data (@file) { chomp; ($contents, $name) = (split(/<>/, $data)); if ($contents eq $in{'id'} && $name eq "" ){ print "<OPTION value=\"無商品\">現在購入できる商品はありません</OPTION>\n"; }else{ print "<OPTION value=\"未選択\">商品名を選択してください</OPTION>\n"; } } IDはジャンル名でnameは商品名です。この状態だと、各項目が複数出てしまいます。 何かこれ以上に足りない情報があれば指摘してください。すぐに記入します。 よろしくお願いします。

    • 締切済み
    • CGI
  • ログファイルを削除するcgiプログラム

    ログファイルを削除するcgiプログラム -------------------- $GYOUSUU = $FORM{'GYOUSUU'}; #--- ログファイルオープン open(FH,"***.log"); flock(FH,2); @FILES = <FH>; flock(FH,8); close FH; undef $FILES[$GYOUSUU]; open (FH2,">***.log"); @filew = "@FILES\n"; print FH2@filew; close(FH2); -------------------- となっているのですが、修正後にログファイルの行の頭に、半角スペースが入ってしまいます。 どこを修正すればいいのでしょうか?

    • ベストアンサー
    • Perl
  • リストに何も無ければXXを表示…

    あるCGIのログの一部をSSIで表示させようとしています。リストの「pt」と「name」があったものだけを「$max」個表示すると言う物です。 一部抜き出すと… ----- print "Content-Type: text/plain\n\n"; open (FILE,"../../cgi-bin/navi-a/navi.log"); $i=0; while (<FILE>) { local($no,$pt,$sub,$hp,$name,$email,$pw,$msg,$dt,$ts,$rec,$axs) = split(/<>/); if ($pt eq $ARGV[0] && $name eq $ARGV[1]){ $i++; print "~ } if ($i >= $max) { last; } } ----- これに、「合う物が無かったら"無いですよ"文を表示」と言うのを付けたいのですが、うまく出来ません。 if ($pt eq $ARGV[0] && $name eq "") とかを試してみましたがうまく出来ませんでした。 何か良い方法が無いでしょうか? お願いします。

    • ベストアンサー
    • CGI
  • 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
  • ファイルの配列のリストデータ(変数)の特定の変数の値だけを変えたい。

    サブルーチンの下のコードで表題の事をやろうとしていますが、 1)値が変わりません。($sinkou) 2)「エラー2','メッセージファイルが開けませんでした.」と表示されてしまいます。 3)モジュールで実現する方法がアったら教えてください。 よろしくお願いします。 sub SET_sinkou{ my($number,$name,$sinkou,@new,$line,$hanabi,$sinkou2); $lockfile = "$tmp_dir$cmd{'log'}\.lock"; &lock; if (!open(DB,$message_file)) { &Error('エラー1','メッセージファイルが開けませんでした.'); } while(<DB>){ ($number,$name,$sinkou) = split(/\t/,$_,3); if($number == $_[0] ) { $sinkou = $_[1]; $sinkou2 = $_[1]; #チェック用 $hanabi='花火'; #チェック用 $line=join(' ',$number,$name,$sinkou); push @new,$line; } else{ $line=join(' ',$number,$name,$sinkou); push @new,$line; } } close DB; if (!open(DB,">$message_file")) { &Error('エラー2','メッセージファイルが開けませんでした.'); } foreach(@new){ print DB $_; } close(DB); unlink($lockfile); &Html_head; print <<"EOF"; $body <h2><strong>変更しました。$sinkou=$sinkou=2=$_[0]=$_[1]=$hanabi</strong></h2><p> <!--$sinkou=$sinkou=2=$_[0]=$_[1]=$hanabiは値のチェック用--> </body></html> EOF }

    • ベストアンサー
    • Perl
  • PHP4→5にアップグレードしたらコードが動きません。

    このコードを使うとエラーが出ます。PHP4の環境では問題なかったのですが、PHP5にしたとたんエラーが出てコードが動きません。このコードは指定のファイルをブラウザでダウンンロードできるスクリプトです。 プログラミング素人なのでどう直したらま動くようになりますか??? #!/usr/bin/perl -wT use CGI ':standard'; use CGI::Carp qw(fatalsToBrowser); my $files_location; my $ID; my @fileholder; $files_location = "/home/user/public_html/static/file"; $ID = param('ID'); if ($ID eq '') { print "Content-type: text/html\n\n"; print "You must specify a file to download."; } else { open(DLFILE, "<$files_location/$ID") || Error('open', 'file'); @fileholder = <DLFILE>; close (DLFILE) || Error ('close', 'file'); open (LOG, ">>//home/user/public_html/dl.log") || Error('open', 'file'); print LOG "$ID\n"; close (LOG); print "Content-Type:application/x-download\n"; print "Content-Disposition:attachment;filename=$ID\n\n"; print @fileholder } sub Error { print "Content-type: text/html\n\n"; print "The server can't $_[0] the $_[1]: $! \n"; exit; }

    • ベストアンサー
    • PHP

専門家に質問してみよう