• ベストアンサー

ログファイルの指定行に書込み

open(IN,"$log") || &error("Open Error"); @data = <IN>; close(IN); while (100 <= @data) { pop(@data); } open(OUT,">$log") || &error("Write Error"); print OUT "$in{'id'}<>$in{'comment'}\n"; print OUT @data; close(OUT); ログにはID、時間、コメントが登録されています。 送信データの中に、ログに登録済みのIDがある場合には、そのIDのある行のみを書き換えたいのですが、方法がどうしてもわかりません。 $logに記録されるIDの順番は以下のようにランダムです。IDに登録される文字列は1からの数値のみです。 52<>コメント 120<>コメント 35<>コメント 8<>コメント 2<>コメント 19<>コメント 85<>コメント よろしくお願いいたします。

  • fx2
  • お礼率93% (29/31)
  • Perl
  • 回答数7
  • ありがとう数7

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

  • ベストアンサー
  • W_H
  • ベストアンサー率47% (21/44)
回答No.7

多分これが最後かな? while (100 <= @data) { pop(@data); } unshift(@data,"$in{'id'}<>$in{'comment'}\n"); の処理は、 my $remain_count = 100; my $remain_count = $remain_count - 1; splice(@data, $remain_count - scalar @data) if (@data > $remain_count); unshift(@data,"$in{'id'}<>$in{'comment'}\n"); と同じです。 上も下も、まず配列の数を指定数-1まで、減らし、次の行でデータを追加して、指定数に調整されています。処理の結果はどちらも同じです。 どちらか好きな方を使えばいいと思います。 後、データの数など、後で変える可能性のある数字は変数にして、なるべくソースの初めの方にまとめて書いた方がいいです。後で編集が楽ですし。(つまり、上のソースを使う場合、100を$remain_countに変え、$remain_count=100;をソースの始めの方に記述する。) 配布されているCGIは設定がすべて初めの方にきていますよね?あれと同じです。

fx2
質問者

お礼

最後までお付き合いくださり有難うございます。いろいろと大変勉強になりました。

その他の回答 (6)

  • W_H
  • ベストアンサー率47% (21/44)
回答No.6

一応#4の質問について #2の最後にやり方は書いてますが、elseの方には、上書きしない場合の処理(つまり何もしない)が入るので、ループを潜り抜けた『後』に処理が必要になります。 楽な手として、ループの前に[$check=0;]というチェック用の変数を作っておき、#値を代入、のすぐ次の行に、値を代入したという変数、[$check=1;]を書きます。else{}の方に書いたら駄目です。 これで、ループ終了時に1となっていれば、データが上書きされたため新規データを追加する必要がないので、ループを抜けた後 if($check !=1){#上書きしていない unshift(@data,"$in{'id'}<>$in{'comment'}\n"); }else{} このような処理をくわえれば、配列にデータを追加できます。 これは先頭に追加していますが、末尾に追加したい場合は、unshiftの代わりにpushを使えばできます。 ちなみに、@linesですが、必要ないです。 普通に実行したら、何も上書きされません。(@linesには@dataのデータがそのままpushされている。)一応@dataの中身を上書きしているので、@lineが絡む処理2行は不必要で、ファイル出力のprintのところを、@dataに書き換えれば、正常に動くと思います。 何でわざわざ@dataの中身を上書きしたかというと、fx2さんの考え方は、ノートの左に書かれた英文を右に写しつつ、ある英文はちょっと変えて書くという作業になります。 ぼくの場合、それは面倒なので、左のページの英文を見て、ある英文だけ消しゴムで消し、書き換えるという作業にしました。 実際やらなくても分かりますが、後者のほうが楽なので、ぼくのサンプルソースは後者を選択しています。 一応ソースはそろったので、後はがんばってください。

fx2
質問者

お礼

わかりやすくご説明してくださり有難うございます。以下のように書きましたところ、おかげさまで成功しました。あと、popのところが間違っていないでしょうか。 open(IN,"$log") || &error("Open Error: $log"); my @data = <IN>; foreach(@data){#配列を回す my($fid,$comment)=split(/<>/,$_);#データ分割 if($fid==$in{'id'}){#ID比較 $_="$in{'id'}<>$in{'comment'}\n";#値を代入 $check=1; } } if($check !=1){#上書きしていない while (100 <= @data) { pop(@data); } unshift(@data,"$in{'id'}<>$in{'comment'}\n"); } close(IN); open(OUT,">$log") || &error("Write Error: $log"); print OUT @data; close(OUT);

fx2
質問者

補足

popのところを以下に変更してみました。よろしいでしょうか。 my $remain_count = 5; my $remain_count = $remain_count - 1; splice(@data, $remain_count - scalar @data) if (@data > $remain_count);

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.5

どのようなスタイルで記述するかということについては、自分なりに 「こうすればいいんじゃないの?」というのはありますが、まあそこはそれ 押し付ける気はないです。 #ファイルオープンが成功したかどうかのチェックとかは忘れないで欲しいとは思いますが ただ、新しい使い方にも明確なメリットというのがありますので、 Perl4時代の書き方が単純でいいというのも一度考えてみてはどうかと思います。 たとえば、ファイルをオープンするときに IN/OUT のような大文字の シンボルを使わないで変数を使うのを取り上げてみると、サブルーチンと このファイルハンドルをやり取りするのに、大文字のシンボルを使ったときと 使いやすさがぜんぜん違います。 #まあ古いバージョンだとできないという問題はありますが ということを挙げていくときりがないのとオフトピなのでやめといて > 、このスクリプトだと重複する可能性があるということでしょうか? すみません。 ここの仕様でインデントがつかないこともあって読み違えてました。 重複はしないですね。 #4のお礼にある質問はわたしが答えない方がいいかな?(笑

fx2
質問者

お礼

いろいろとご親切にご指導くださり感謝いたします。今まで人のソースをみながら自己流で何となく覚えてきたような感じなのですが、やはり本格的に勉強しなくてはと改めて思った次第です。ご紹介いただいた本も早速注文させて頂きました。ありがとうございます。

fx2
質問者

補足

すみません、ANo.6への「この回答への補足」で間違えました。my $remain_count = $remain_count - 1;は削除しまして、unshiftの下の行にspliceを追加しました。

  • W_H
  • ベストアンサー率47% (21/44)
回答No.4

sakusaker7さんへ。 一応ぼくのここでの書き方は、構造が見て分かりやすい(基礎的な関数を使う)、というのを重視しています。多分過去の回答とかを見たら、ものすごく突っ込みたくなると思います。なので、文法も一応チェックに引っかからないレベルとなっています。(ループ外ではmyなどを使わないなどしているため。) 後、参考書とforeach使用時の値代入方法を教えていただき、ありがとうございます。後々役立てさせてもらいます。 foreachに関しては、配列の時によく使っていたのですが、今回の使い方を知らなかったので、ここしばらくまともに使ってませんでした。個人的に好きな(楽な)関数だったので、本当にありがとうございます。 お礼だけだと無意味となるので、早速foreachを使ったサンプルソースを…… foreach(@data){#配列を回す my($fid,$comment)=split(/<>/,$_);#データ分割 if($fid==$in{'id'}){#ID比較 $_="$in{'id'}<>$in{'comment'}\n";#値を代入 }else{} } 前回同様@dataと$in{~}は省略しています。一応宣言していない$nを使うforを使っていないのでuse strictにも(配列とハッシュの宣言さえすれば)引っかからないようになってます。 あくまでこれは基本的考え方なので、他の改造はがんばってください。

fx2
質問者

お礼

ご回答有難うございます。また、ご丁寧に説明も入れてくださり大変助かりました。 @lines=(); open(IN,"$log") || &error("Open Error: $log"); @data = <IN>; foreach(@data){#配列を回す my($fid,$comment)=split(/<>/,$_);#データ分割 if($fid==$in{'id'}){#ID比較 $_="$in{'id'}<>$in{'comment'}\n";#値を代入 }else{ } push(@lines,$_); } close(IN); open(OUT,">$log") || &error("Write Error: $log"); print OUT @lines; close(OUT); このような感じでよろしいのでしょうか。 $in{id}に等しいidを持った行がなかった場合に、新規で書き出すには、 }else{ この部分にどのようにかけばいいのか、どうしてもわかりませんでした。 } お手数をおかけいたしますが、よろしくお願いいたします。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.3

#1です。 #1で示したスクリプトは実行して確かめてますので、出力結果が期待したものと違う というのならわかりますが、実行もできないエラーというのはなんなんでしょう。 ひょっとして使っているPerlのバージョンがとっても古かったりしますか? とりあえず理解できる範囲で書くというのでもいいと思うので、それを念頭に考えてみると > if ($noid !~ /1/) { $noid は 0 か 1かのどちらかの数値ですので、わざわざ正規表現という 「重い」処理を持ち出さずに $noid != 1 というように数値としてみてやる方が良いでしょう。 !~ /1/ という正規表現と比較すると意味が違いますし。 #ぶっちゃけ 200 と比較しても成功してしまいます また、ログの切り詰めのために ・ファイルを読み出しのためにオープン ・書き戻しのためにオープン ・再度読み出しのためにオープン ・再度書き出しのためにオープン というのはいかにも無駄です。 それと、配列の要素数をある数以下にするのにpopを何回も呼ぶのは無駄です。 #1の回答に書いたように、spliceを使えば一回の関数呼び出しで必要な要素数に 丸めることが可能です。 一つ確認なんですが#1のお礼にあるスクリプトだと、 あるidを持った行が2行以上存在する可能性がありますけどそれは良いのでしょうか? idをチェックして内容を書き換えるくらいだから、書き換えた場合は $in{id}と$in{comment}の内容をファイルに書き出すことはないと思ったんですが。 ついでに。 > こんな感じで、配列をforとか配列をカウントできるようにします。 Cスタイルの for ではなく、foreach (forと書いても一緒なんですが)スタイルを使えば、 foreach (@data) { ... } と書けば、配列の要素数を調べる必要もありません。 Perlのバージョンが古い(5.004とかその辺?)もので、なおかつ配列が巨大な ものだとメモリをバカ食いしたりしますが、その挙動は修正されています。 添え字を使うこと自体に意味があるのでなければ、foreach。です。 念のため書き添えておきますが、 foreach (@data) { $_ *= 2; } のようにデフォルト変数(もしくは自分で宣言した変数)に対して 書込み操作をすれば、配列の内容の方もちゃんと書き換わります。 > $#配列名で配列の数(配列の数え方なので、配列の数-1) 微妙に違います。 特殊変数 $[ をいじることはご法度なので、これでもまあ間違いではないのですが 配列の要素数を求めるには $#配列変数名 ではなく、スカラーコンテキストで 配列を評価すればOKです。 use strict; しましょうとかほかにも書きたいことはありますが とりあえず自粛しておきます。 時間的な余裕があったらこの辺の本を読んでみるのをお勧めします。 Perlプログラミング救命病棟: 本: ピーター・J・スコット,トップスタジオ,伊藤 直也 http://amazon.jp/dp/4798109401 CGIなら、CGI.pmとかCGI_Lite.pmを使った方が楽できると思うのですが わかりやすい日本語で書かれた入門記事はあるんですかねえ。

fx2
質問者

お礼

わかりやすくご説明してくださり有難うございます。以前に、超初心者用の入門書で勉強を始めたことがあったのですが、意味がわからずに挫折したままになっていました。Perlの改造は、意味はあまりわかっていないのですが、皆さんのソースをみながら何となく見よう見まねで少しずつ覚えている程度の知識しかありません。 調べてみましたところ、perlは5.8.8が利用されているようです。 多分、私のスクリプトの書き方がメチャクチャなため、use strict;を使うとエラーが生じたのかもしれません。 今は時間ぎりぎりで生活しているような感じですが、余裕がでてきましたら、ご紹介いただいた参考本で勉強を始めてみようと思います。

fx2
質問者

補足

>> 一つ確認なんですが#1のお礼にあるスクリプトだと、 >> あるidを持った行が2行以上存在する可能性がありますけどそれは良いのでしょうか? もうしわけありません、未熟なために自分が書いている内容もあまり理解できていません。登録を行う際に、idが重複されないように作りたかったのですが、このスクリプトだと重複する可能性があるということでしょうか?

  • W_H
  • ベストアンサー率47% (21/44)
回答No.2

いやぁ、データの区切りを同じ(<>)にしてる人いるんですね。なんだか親近感を覚えてます。(笑 それはさておき、簡単にこういう場合の基礎的なの載せときます。ファイルへの読み書きは省略して、@dataにファイルデータが。$in{~}に例の新しいデータが入っているとします。 for($n=0;$n<=$#data;++$n){#配列の数だけループ my($fid,$coment)=split(/<>/,$data[$n]);#データ分割 if($fid==$in{'id'}){#ID比較 $data[$n]="$in{'id'}<>$in{'comment'}\n";#値を代入 }else{} } こんな感じで、配列をforとか配列をカウントできるようにします。whileでもできるけど、わざわざカウントしないといけないので面倒です。 $#配列名で配列の数(配列の数え方なので、配列の数-1)が取得できるので、それを使って、上手くループを回します。 で、そのたびにデータを分割(split)し、ID値を比較し、同じ場合は、その変更する配列のデータ($data[$n])を、新しいデータに書き換え、それ以外のときは、何もしないというプログラムを書けば、自然と@dataの中身は更新されます。 後応用は、それが実行されなかったら新しく追加するなどの時に、ifの中に、実行されたことを表す変数と値を代入し、例えば変数の中身が1の場合は、配列に新規データを追加する、などの処置が入ってくると思います。 文法チェックをしてないので、間違っていたらごめんなさい。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

最大で100行ログを残すけれども、そのとき $in{id}に等しいidを持った行があった場合に それは更新して書き出したいということですか? であるならこんなところでどうでしょうか use strict; my $logfile = 'sample.log'; my $remain_count = 100; #for debug my %in = (id => 35, comment => "new comment"); open my $ifh, '<', $logfile or &error("Open for read Error $!"); my @data = <$ifh>; close $ifh; splice(@data, $remain_count - scalar @data) if (@data > $remain_count); @data = map {$in{id} == (split /<>/, $_)[0] ? "$in{id}<>$in{comment}\n" : $_} @data; open my $ofh,'>', $logfile or &error("Open for write Error $!"); print $ofh @data; close $ofh;

fx2
質問者

お礼

ご回答有難うございます。設置してみましたところ、以下のエラーが表示されてしまいました。素人なみの私の知識では、ソースの意味も、エラー内容もよくわかりませんでした。申し訳ありません。 Script Error The script did not produce proper HTTP headers. Please see the error log to see the detail of the errors. Depending on the server configuration, you can also run thisscript under CGIWrap debugging. Usually, either rename or linkthe script temporarily to a file which ends with .cgidextension, or add a AddHandler cgi-script-debug .cgiline to your .htaccess file. ------------------------------- 昨日からいろいろなCGIやら、サイトを参考に自分なりに工夫して組み立ててみましたところ、以下スクリプトで一応、思い通りの動作をしました。ですが素人が適当にやってたまたま出来た方法ですので、書き方がメチャクチャな気がして、バグもありそうで、心配です。 以下内容のスクリプトでも大丈夫でしょうか?もしこのように修正した方がよいという箇所がございましたら、お教え頂ければ幸いです。よろしくお願いいたします。 @lines=(); open(IN,"$log") || &error("Open Error: $log"); while (<IN>) { ($id,$comment) = split(/<>/); if ($in{'id'} == $id) { $noid=1; $_ = "$in{'id'}<>$in{'comment'}\n"; } push(@lines,$_); } close(IN); open(OUT,">$log") || &error("Write Error: $log"); print OUT @lines; close(OUT); if ($noid !~ /1/) { open(IN,"$log") || &error("Open Error: $log"); @data = <IN>; close(IN); while (100 <= @data) { pop(@data); } open(OUT,">$log") || &error("Write Error: $log"); print OUT "$in{'id'}<>$in{'comment'}\n"; print OUT @data; close(OUT); }

関連するQ&A

  • 指定行に書込み

    open( IN, "log.cgi" ); @f_data = <IN>; close( IN ); $i = '1'; open( OUT, ">dat.cgi" ); select OUT; print "document.open();\n"; print "document.write('"; foreach( @f_data ){ if( $i > 5 ){ last; } ( $f_data1, $f_data2, $f_data3, $f_data4 ) = split( /<>/ ); $f_data1 =~ s/ //g; print "$f_data1"; $i++; } print "');\n"; print "document.close();\n"; select STDOUT; close( OUT ); 上記スクリプトで、指定された行数、又は指定された場所でdat.cgiに 書き出したいのですが、どのように書けばよろしいのでしょうか? 例えば、 ・100行目に書き出す。 または、 ・指定された文字列の間に書き出す。 (例)<!--開始-->ここに書き出す。<!--終了--> このどちらかが出来ればいいのですが、上記スクリプトをどのように変更すれば可能になるでしょうか?お手数ですが、どうぞ宜しくお願いいたします。

    • ベストアンサー
    • Perl
  • 全行読み込むには

    open( IN, "pass.dat" ) or die "Can't open pass.dat: $!"; $f_data = <IN>; close( IN ) or die "Can't close pass.dat: $!"; $f_data1 = $f_data; $f_data2 = $f_data; $f_data1 =~ s/<br>//g; $f_data2 =~ s/\S//g; open( OUT, ">log.dat" ) or die "Can't open log.dat: $!"; select OUT; print "$f_data1"; print "$f_data2"; select STDOUT; close( OUT ) or die "Can't close word.js: $!"; 上記スクリプトでは、pass.datの一行目しか読み込まれません。全行を読み込むためにはどのように書き換えればいいのでしょうか?宜しくお願いします。

    • ベストアンサー
    • 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
  • ログの一部を消す Perl

    ログの一部を消すPerlを考えています。 ここではソースを短くするために、ログの一部を消し去って ログファイルに上書きするデータは $deta だけだとすると open F, '+<a.log'; flock F,2; $deta = <F>;//実際はここでもっと処理 truncate F,0; seek F,0,0; print F $deta; close F; と、 open IN, 'a.log'; flock IN,2; open OUT, '>a.log'; flock OUT,2; $deta = <IN>;//実際はここでもっと処理 print OUT $deta; close OUT; close IN; の2つを考えました。 上のように 読み込み と 書き込み を同時にやった方がいいのか 下のように分けてやった方がいいのか教えてください。 ロックは flock を使って、普通レベルのロックが できるぐらいでいいと思っているんだけど、 この flock の書き方でおかしいところがあれば 教えてください。

    • ベストアンサー
    • CGI
  • ファイルの書き込み2

    またまた失礼します。 やりたいことは以下です。 1.ディレクトリを開く。 2.ファイル達を読み込み。 3.追記用のデータファイルを開く。 4.「2」にデータを追記 5.別のディレクトリに書き出し。 以上です。 4番がうまくいきません。 ためしに4の工程を抜かすと問題なく書き出されます。 4の工程でやりたいことは、 1.タブ区切りのテキストファイルを読み込み。 2.書き出し用に読み込んだ(追記したいファイル)<productのpath="[ココの値!]"を取得。 3.「2」番で取得した値と「1」番で取得した値を比較。 4.「3」がtrueの行を追記して書き出し。 以上。 要するになにがしたいかというと、 仮にタブ区切りテキストには10行分のデータがあるとします。 それぞれの行には3つ分の値が入っており、先頭にIDが付いています。 一番最初に読み込んだファイル(追記したいファイル)にも同様にIDが振られており(<product path="ココ")そのIDとタブ区切りテキストのIDが一致した行だけ追記したいということです。 下記のコードだとなぜか、 10行分のデータがすべて追記されてしまいます。 コードは以下です。 #!/usr/bin/perl #既存ファイル読み込み&追記 $n_dir = "newXml/"; $b_dir = "xml/"; opendir(DIR, $b_dir); while($file = readdir(DIR)){ $bfile="$b_dir$file"; $nfile="$n_dir$file"; $dfile="data/data.txt"; if (-T $bfile) { open(IN, $bfile);#既存ファイルオープン @list = <IN>; close(IN); open(OUT,">$nfile");#書き出しファイルオープン foreach $line (@list) { if ($line =~ /\<product/){ $line =~ /path=\".*\"/;#path取得 $1; } if ($line =~ /\<\/product\>/) { open(IN, $dfile);#追加データファイルオープン while($data = <IN>){ chomp(@data = split(/\t/,$data)); $data[0] =~ s/\//_/g; if($data[0] == $1){#取得したパスとdata.txtとってきた値を比較 print OUT <<EOF; <ds path="$data[0]">$data[1]</ds> <kw>$data[2]</kw> $line EOF } else{next;} } close(IN) }else{print OUT $line;} } close(OUT); } else{next;} } closedir(DIR); 長々と申し訳ありません。 エラーなどは特にありません。 ご協力お願いします。

    • ベストアンサー
    • Perl
  • ログを新しい順に保存

    始めまして。お世話になります。 初心者ですがどうぞよろしくお願いします。 cgiでメールフォームを作成しており、ログをテキスト形式で保存するように設定しています。 ログ自体は正しく保存できるのですが、 新しい順にログを保存する方法を参考書を元に以下の通り記述したのですが、新しい順になりません。 open OUT,">> log.txt"; print OUT $data,"\n"; close OUT; open IN,"log.txt"; @txt = <IN>; @txt = reverse @txt; close IN; どこを変更すればよいのかアドバイスをいただけませんでしょうか。 よろしくお願いします。

    • ベストアンサー
    • CGI
  • csvデータの開始行と最終行を全体の4分の1で区切り処理をしたい

    csvデータの開始行と最終行を全体の4分の1で区切り処理をしたい csvデータの開始行と最終行を全体の4分の1で区切り処理をしたいと思ってます。 csvファイルは20万件あります。4分の1なので1~50000件となります。 今回は50001~100000件までを行いたいのですが、先日教えていただいたwhile($lines = <IN>) ですと、最初から1件ずつ最終行まで処理をしてしまいます。 (ここから) open(OUT,">$csv"); open(IN,"$data") || &error(" $data を読み込みopen出来ません"); while($lines = <IN>) { ($seq1,$categ,$password,$imail,$cont) = split("\,", $lines); $cont .= " "; $data = "$seq1,$cont,1\n"; print OUT "$data"; $data = ""; } close IN; close OUT; (ここまで) 今回は20万件ですが、毎回このデータ量は月次ごとに変わります。 while周辺をいじるような気がしていますがどのようになるのかがわからなかったので質問いたしました。 お手数かけます。 よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • 掲示板の文字色指定について

    はじめまして。私は学生で超のつく初心者なのですが、課題で掲示板を作っています。 基本的な表示はなんとかうまくいったのですが、よくある、文字色を選択して好きな色で文章(コメント)を表示させるプログラムがわかりません。 if文を使うパターンではなく、色の情報を書き込み、ファイルからデータを読み込むやり方でできるらしいのですが、どうやって書いたらよいのでしょうか・・・。 ちなみにhtml表示部分に、色の指定はしてあり、赤、青、緑、黄色でvalueはred,blue,green,yellowにしています。 下に書き込みと読み込みの部分を乗せたのですがどう入れたらいいでしょうか。 本当に初心者だし分かっていないので説明もわかりにくくてすいません。もしどなたか分かる方いたらよろしくお願いします。 #------------------------------------------------------------ # 登録データ書き込み処理 #------------------------------------------------------------ sub writeData() { # $DATAFILEをオープンする open(FILE, ">> $DATAFILE") or die("error:$DATAFILE open error!"); eval{ flock(FILE, 2); }; $timestr = &getTimestr(); $in{'comment'} =~ s/\n/<br>/g; print FILE "$in{'namae'},$in{'dai'},$in{'comment'},$timestr,"; close(FILE); } #------------------------------------------------------------ # 登録データ読込み処理 #------------------------------------------------------------ sub readData() { # $DATAFILEをオープンする open(FILE, "< $DATAFILE"); eval{ flock(FILE, 2); }; while(<FILE>){ chomp; $line[$cnt++] = $_; } close(FILE); }

    • ベストアンサー
    • CGI
  • ログファイルへの書き込みがうまくいきません

    ------------------------------------------ open(LOG,"+<$filename") || die "Error!\n"; @logs=<LOG>; flock(LOG,2); unshift(@logs,"$array[0],$array[1],$array[2],$array[3],$array[4]\n"); print LOG @logs; flock(LOG,8); close(LOG); ------------------------------------------ この$array[0]~$array[4]にはそれぞれ、「<option value="1">1</option>」の様な、プルダウンメニューの「1~10」までの数字が入っています。 この数字を$filenameへ書き込みたいのですが、中々うまくいかずに困っています。 ちなみに、一応書き込めるには書き込めるのですが、$filenameを開くと、 ------------------------ 1,1,1,1,1 6,4,1,9,6 1,1,1,1,1 9,1,2,4,4 1,1,1,1,1 3,0,1,9,5 1,1,1,1,1 ------------------------ このような形になってしまいます。何がいけないのでしょうか? よろしくお願いします。

    • ベストアンサー
    • Perl
  • perlでテキストデータの指定行に書き込み

    たびたびお世話になります。 データには、「データNO」「登録NO」「名前」「カテゴリー」「金額」が登録されています。 もともとあったデータをフォームで編集、送信してデータNO($d_no)と一致した行だけを書替え(上書き)したいんですが、どうしても方法がわかりません。 open(IN,"../save_data/sdeta.txt"); @data = <IN>; close(IN); foreach(@data){ chop($sdata); ($d_no,$s_no,$s_name,$d_class,$s_price) = split (/=/, $sdata); if( $value eq $d_no){ $sdata="$in{'d_no'}=$in{'s_no'}=$in{'s_name'}=$in{'d_class'}=$in{'s_price'}\n"; }else{ $sdata="$d_no=$s_no=$s_name=$d_class=$s_price\n" } } open(OUT,">../save_data/sdeta.txt") || &error("オープンエラー"); print OUT @data; close(OUT); 上のプログラムを書いても、書替えできませんでした。 どのように直せば一行のみの書替えが出来るんでしょうか。 よろしくお願い致します。

    • ベストアンサー
    • Perl

専門家に質問してみよう