• 締切済み

cgiのログの書き方

ここで教えてもらってログファイルの書き方(挿入のようなカンジで)をやってみたんですが、どうしても思い通りの動きをしません。 希望としては、IDが一緒なら、その同じIDの下に書き込みを行う。同じIDが見つからなければ、一番上に書き込みを行う。 というようにしたいのです。 上記のことを行うために以下のコードを書きました。 --------------- for ($w=0;$w<$gyou+1;$w++){ @log3 = split(/&/,$log2[$w]); foreach(@log3){ ($keyw,$valuew) = split(/=/,$_); $FORMw{$keyw} = $valuew; }#foreach open(FH3,">>log.log"); if ($ID == $FORMw{'ID'}){ print FH3"ID=$ID&COUNT=$COUNT&TITLE=$TITLE&NAME=$NAME&PASSWORD=$PASSWORD&NAKAMI=$NAKAMI&COLOR=$COLOR&TIME=$year/$m on/$day $hour:$min:$sec&SEARCHKEY=$year$mon$day$hour$min$sec\n"; last; } else { if($w+1 == $gyou){ print FH3"ID=$ID&COUNT=$COUNT&TITLE=$TITLE&NAME=$NAME&PASSWORD=$PASSWORD&NAKAMI=$NAKAMI&COLOR=$COLOR&TIME=$year/$m on/$day $hour:$min:$sec&SEARCHKEY=$year$mon$day$hour$min$sec\n"; close(FH3); } } }#for --------------- どうしてもログファイルの最新情報としてしか書き込みがされません。 また、最新ログを1番上に書き込む、ということをしたいのですができますか? 日付順などで並べ替えをしてしまうと、ぐちゃぐちゃになってしまうので、並べ替えを行わずに、です。 またこのような書き込みの仕方をしなくても、 例えば並べ替えで、Excelみたいに、1番目と3番目を基準に並べ替え、とかでできますか? (私は1つの方法でしか知らないので、どうしても意図する順番になりません。)

みんなの回答

  • estea
  • ベストアンサー率44% (39/87)
回答No.5

はい。ごめんなさい。バグってます。 > 4.追加したいIDかを判断する。追加したいのであれば 5、そうでなければ 6 へ。 >5.まず $lines[$a] を書き出し。 で、次に%FORMを整形して書き出し。 >6.$lines[$a]を書き出し。 ># 4. 5. 6. は まとめると以下の4行.... >  print $line; >if( $ID == $FORMw{ID} ){ >   print LOG "ID=$ID&COUNT=$COUNT&TITLE.... とあるうちの >  print $line; は   print LOG $line; の誤りでした。

すると、全ての回答が全文表示されます。
  • feininger
  • ベストアンサー率41% (74/180)
回答No.4

> しかし、「同じIDがあった場合、それの下に書き込む」ができません。 フラグが必要かと。こんな感じ↓ $insert_line = 挿入したい行; $flag = 0; foreach (読み込んだログ) {  $current_line = $_;  if ($flag == 0) {IDが一致したら$flag = 1;}  if ($flag == 1) {IDが異なったら$insert_lineをログに書き込み; $flag = 2;}  $current_lineをログに書き込み; } if ($flag < 2) {$insert_lineをログに書き込み;} 終了;

KODAMAR
質問者

お礼

みなさま回答ありがとうございました。 自分なりのやり方でなんとかできました。 (大分遠回りのやり方ですが、こうでもしないと自分でわからないので) 方法としては、 ●IDが一致したものの前までのログ ●IDが一致したものの親ログ ●IDが同じ書き込み(実際の入力) ●それ以降のログ にわけ、それぞれを書き込むようにしました。

すると、全ての回答が全文表示されます。
  • estea
  • ベストアンサー率44% (39/87)
回答No.3

全体的なソースが出てきて全容がつかめそうなのですが、何がしたいかふめいでつ。何処と聞かれれば全体ですと答えるしか・・・ 私が全部書き直していいのですか? 先にも書きましたが、流れに沿ってもう少し具体的に書きましょう・・・。 1.ログファイルを全部 @lines に読み出す。  open(LOG,"log.log");  @lines = <LOG>;  close(LOG); 2.読み出しに開いたファイルを閉じて書き込み用に開ける( ">>" では無く ">" です。)  open(LOG,">log.log"); 2.foreach などで @lines を順番に以下のことを行なう foreach $line(@lines){ #foreach1 3.$lines[$a] などに対して各データに分ける( split ~ ってやつ。)   foreach(split(/&/,$line)){ #foreach2 >  ($keyw,$valuew) = split(/=/,$_); >  $FORMw{$keyw} = $valuew; > } #foreach2 #↑一応こんなのでいいはずだが <> や タブ なんかで分けてると #ココがもっと楽。 4.追加したいIDかを判断する。追加したいのであれば 5、そうでなければ 6 へ。 5.まず $lines[$a] を書き出し。 で、次に%FORMを整形して書き出し。 6.$lines[$a]を書き出し。 # 4. 5. 6. は まとめると以下の4行....   print $line; if( $ID == $FORMw{ID} ){    print LOG "ID=$ID&COUNT=$COUNT&TITLE....   } } #foreach1 clsoe(LOG); ########################################## ・・・大分変わっちゃいました。上記ソースは当然動作未確認... で、示していただいたソースの問題点は以下のとおり。 1. if($ID=.... の扱い。 if で囲まれた中にしか print 命令が無い 2. split で & や = を切っているが一考の余地あり。データのフォーマットを再考してください。 3. last が不明。 for の中の if の中の for といったネストが微妙。 ##################################### で、今になって誤解が発覚したのだが、 追加したデータって $ID とか $COUNT だったのな。 %FORMw だと思ってた。 なもんで、以前までの投稿は微妙に間違ってた。すまぬ。

KODAMAR
質問者

お礼

回答ありがとうございます。 ログファイルを開く時に>(書き込み)で開くと、どうしてもすべてのログが消えてしまうのですが。 それとご指摘の通り、ログファイルを<>で区切るようにしました。 ($ID<>$COUNT<>$TITLE…というカンジです。) これですとどんなカンジになりますか? 今自分でつくった流れとしては トップページ(新規入力→Aへ。 返信入力→Bへ) A フォームを表示。 ログファイルを開き、すべてのIDを調べ、1番大きなIDに1を足したものをIDとしてわりあてる。 ログファイルの中身が空っぽならそのままログファイルへ書き込み。 すでにログファイルの中身があれば、現在入力されたデータ+すべてのログファイルという形で書き込みを行う。 ($COUNTはすべて1) B 返信入力なので、親書き込みのIDをわりあて。 $COUNTは親IDの$COUNTに1を足す。(なので2となる) ログファイルを開き、同じID(親書き込み)を探す。 同じIDがみつかったらその下の行へ書き込みを行う。 親IDが1番下とは限らないので、真ん中だったり一番下への書き込みとなる。 (返信なので1番上はありえない。) となってます。 Aはすべてできました。 Bの4行目でひっかかっています。 教えていただいたものを実行してもログが消えてしまいます。 どうぞよろしくお願いします。

すると、全ての回答が全文表示されます。
  • estea
  • ベストアンサー率44% (39/87)
回答No.2

どもも。 ログってことですが、何を目的にしているかにもよりますが余りいただけない書式ですな・・・ ファイルに記述する場合は、 form から取るときと違って、& で区切られた各値が前後することは絶対にありませんので。 ID=$ID&COUNT=$COUNT..... というのは、それはそれで目的があるならいいのですが単にデータを記録するだけなら たとえば <> や , や タブ符で各値を区切って、 $ID<>$COUNT..... とするほうが良いかもしれません。何かと楽ですす。 で、何が楽かってと、最初の部分でやってる split とか for で回してる部分がもっと効率的に欠けます。 で、話を戻して、追加の方法ですが簡単には以下のようになります。 1.ログファイルを全部 @lines に読み出す。 2.読み出しに開いたファイルを閉じて書き込み用に開ける( ">>" では無く ">" です。) 2.foreach などで @lines を順番に以下のことを行なう 3.$lines[$a] などに対して各データに分ける( split ~ ってやつ。) 4.追加したいIDかを判断する。追加したいのであれば 5、そうでなければ 6 へ。 5.まず $lines[$a] を書き出し。 で、次に%FORMを整形して書き出し。 6.$lines[$a]を書き出し。 見たところ、 $FORMw の書き出しが含まれていませんな。これを"追加"すればいいと思われ。 あと、ログの最初に追加するってのはもっと楽で、全ファイル内容を @lines に読み取ってそこに整形した $FORMw のデータを unshift して、 @lines を書き出すのが一番楽かと。 (seek はめんどくさい...) まだまだ続いて... 複数値によるソートですが、可能です。が、少々面倒で ハッシュを用いたソートでしょうか。

KODAMAR
質問者

お礼

回答ありがとうございます。 どうにか新規書き込み(ログの一番上に書き込む)はできました。 しかし、「同じIDがあった場合、それの下に書き込む」ができません。 下記のようにしてみたのですが…。 open(FH2,"log.log"); @log2 = <FH2>; close(FH2); $gyou = @log2; for ($w=0;$w<$gyou+1;$w++){ @log3 = split(/&/,$log2[$w]); foreach(@log3){ ($keyw,$valuew) = split(/=/,$_); $FORMw{$keyw} = $valuew; }#foreach if ($ID == $FORMw{'ID'}){ open(FH3,">>log.log"); @loglog2 = <FH3>; for($r=0;$r<$gyou+1;$r++){ if($r == $w){ print "wは?$w<BR>\n"; print "rは?$r<BR>\n"; print FH3"ID=$ID&COUNT=$COUNT&TITLE=$TITLE&NAME=$NAME&PASSWORD=$PASSWORD&NAKAMI=$NAKAMI&COLOR=$COLOR&TIME=$TIME&S EARCHKEY=$SEARCHKEY\n"; #print FH3"$ID<>$COUNT<>$TITLE<>$NAME<>$PASSWORD<>$NAKAMI<>$COLOR<>$TIME<>$SEARCHKEY\n"; close(FH3); last; }# if }#for last; : : どこを直せばいいのでしょうか?

すると、全ての回答が全文表示されます。
回答No.1

ぱっと見た感じですが、 おそらく@log2(にデータが入っていて)を分解、 そのIDと今回投稿されたID比較してるのですよね? いくら途中で振り分けても、 print FH3 ~~ と同じように両方とも書き込んでいるので、 両方とも同じくなるのは当然かと思います。 既に@log2にデータが丸ごと入ってるなら、 それに新しいデータを追加して、 全体を書き込んだ方が処理は楽だと思いますよ。 (新しいデータを途中に埋め込む場合は) >最新ログを1番上に書き込む、ということをしたいのですができますか? seek をキーワードに検索してみてください。 >1番目と3番目を基準に並べ替え これももちろんできますが、結構面倒です(^^; sort関数を調べてみると色々例がのっています。 ところで、 何回もファイルが重ねて開かれてるような・・ しかもきちんと閉じてないような・・(苦笑) open~closeとそれにともなうseek/truncateなどや、 ファイルロックについてもう一度確認されてみるといいと思います。 #蛇足ですが、print @sort と print "@sort" "@sort"はPerlが自動的に半角のスペースをいれるのです。 @data = qw(this is useful); print "@data"; #this is useful print @data; #thisisuseful となります。 (つまり、特別に配慮されているということでしょうか) なお、$" で変更できます。

KODAMAR
質問者

お礼

回答ありがとうございます。 ちょっと今すぐに全部には答えられないので、さしあたって少しだけ補足させていただきます。 >>最新ログを1番上に書き込む、ということをしたいのですができますか? >seek をキーワードに検索してみてください。 はい、seek関数に私も行き着きました。 それでつかってみたのですが…どうもちゃんとしてないみたいなんですけど…。 seek(FH3,0,0); print FH3"ID=$ID&COUNT=$COUNT&TITLE=$TITLE&NAME=$NAME&PASSWORD=$PASSWORD&NAKAMI=$NAKAMI&COLOR=$COLOR&TIME=$TIME&SEARCHKEY=$SEARCHKEY\n"; でログファイルの1番最初に入力される(はず)なんですよね? 1番最後に入力されてしまうのですが…。

すると、全ての回答が全文表示されます。

関連するQ&A