dポイントプレゼントキャンペーン実施中!

ここで教えてもらってログファイルの書き方(挿入のようなカンジで)をやってみたんですが、どうしても思い通りの動きをしません。
希望としては、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つの方法でしか知らないので、どうしても意図する順番になりません。)

A 回答 (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;
の誤りでした。
    • good
    • 0

> しかし、「同じ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をログに書き込み;}
終了;
    • good
    • 0
この回答へのお礼

みなさま回答ありがとうございました。

自分なりのやり方でなんとかできました。
(大分遠回りのやり方ですが、こうでもしないと自分でわからないので)

方法としては、
●IDが一致したものの前までのログ
●IDが一致したものの親ログ
●IDが同じ書き込み(実際の入力)
●それ以降のログ

にわけ、それぞれを書き込むようにしました。

お礼日時:2003/09/10 18:13

全体的なソースが出てきて全容がつかめそうなのですが、何がしたいかふめいでつ。

何処と聞かれれば全体ですと答えるしか・・・
私が全部書き直していいのですか?

先にも書きましたが、流れに沿ってもう少し具体的に書きましょう・・・。

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 だと思ってた。
なもんで、以前までの投稿は微妙に間違ってた。すまぬ。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

ログファイルを開く時に>(書き込み)で開くと、どうしてもすべてのログが消えてしまうのですが。

それとご指摘の通り、ログファイルを<>で区切るようにしました。
($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行目でひっかかっています。

教えていただいたものを実行してもログが消えてしまいます。

どうぞよろしくお願いします。

お礼日時:2003/09/10 15:13

どもも。



ログってことですが、何を目的にしているかにもよりますが余りいただけない書式ですな・・・

ファイルに記述する場合は、 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 はめんどくさい...)


まだまだ続いて... 複数値によるソートですが、可能です。が、少々面倒で ハッシュを用いたソートでしょうか。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
どうにか新規書き込み(ログの一番上に書き込む)はできました。
しかし、「同じ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;




どこを直せばいいのでしょうか?

お礼日時:2003/09/09 15:13

ぱっと見た感じですが、



おそらく@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
となります。
(つまり、特別に配慮されているということでしょうか)
なお、$" で変更できます。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
ちょっと今すぐに全部には答えられないので、さしあたって少しだけ補足させていただきます。

>>最新ログを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番最後に入力されてしまうのですが…。

お礼日時:2003/09/09 09:56

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!