- ベストアンサー
データリストにデータが無い場合に追加する
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>";
- みんなの回答 (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");
その他の回答 (2)
- hikomin
- ベストアンサー率63% (40/63)
> 判定の方ですが$Check_listが巨大になる可能性があります。その際のperl ver5で変数の最大文字数の制限ってあるのでしょうか? 多分…ないんだと思います…。今まで、大きなテキストデータ・バイナリデータを全てメモリ(変数)に読み込むという処理はたくさん行ないましたが、今のところ壁にぶつかっていないです…。(すいません、考えた事もなかったです…。)
- hikomin
- ベストアンサー率63% (40/63)
ええと、この結果ですが、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が巨大になる可能性もある。とかとか。)
お礼
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で変数の最大文字数の制限ってあるのでしょうか?
お礼
Etherskyさん、回答ありがとうございます。 参考にさせていただきます。