perlでのデータ処理について

このQ&Aのポイント
  • perlでのデータ処理について困っている方へのアドバイス
  • ファイルの読み込みと書き込みで問題が発生しているかもしれません
  • コードの一部を修正することで問題が解決する可能性があります
回答を見る
  • ベストアンサー

perlでのデータ処理について

みなさんこんにちは、今、perlについてとても困っています。 以下に内容を記載しますので、わかる方がいましたら 良きアドバイスをお願いします。 #使用するファイルは2つです。 #元データ=$files1 #送信データ=$files2 #データの一行処理開始 open(IN,"$files2") || &error("$files1を開けません。"); while (<IN>) { ($no,$id,$mail,$type,$data)=split(/,/); # $files2を一行づつ読み込んで送信処理をしていきます。 . . . . . #ここからが問題点です。 # $files2を一行読み込んで送信が終わったら、$files1へ送信履歴として、 #日付を入力します。以下にスクリプトを記載しますので、良きアドバイスを #お願いします。 &get_date; @logs=(); @new=(); open(LOG,"$files1") || &error("$files1を開けません"); @logs = <LOG>; close(LOG); foreach $log (@logs){ @all_data = split(/,/,$log); if ($all_data[0] eq $id){ # $idは$files2から読み込んだ数値です。 $shori_date="$year\/$w_mon\/$w_mday"; $all_data[33]="($shori_date)($hour:$min)"; for ($i=0; $i<@all_data; $i++){ $work.="$all_data[$i],"; } chop $work; push(@new,$work); }else{ push(@new,$log); } } open(ALL,"+< $files1") || &error("$files1に書き込めません"); flock(ALL,2); truncate(ALL,0); seek(ALL,0,0); print ALL @new; close(ALL); #ここまでです。 #このようにすると、日付は入るのですが、データの更新、書き込みされたファイルを見ると #同じ内容が、2重、3重にコピーされて、ファイルに書き込みされてしまいます。 } close(IN); 以上なのですが、良きアドバイスを教えて下さい。

  • Perl
  • 回答数2
  • ありがとう数1

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

  • ベストアンサー
  • okmotokun
  • ベストアンサー率59% (92/155)
回答No.2

正規表現なんか使わなくても $work=""; でいいです。 これを 使い始める前か、使い終わった後に置きます。while(<IN>)ループの中ならどこでもいいです。 具体的には、【1】~【4】のどこかですね。 ついでですが、@logs=(); には意味がありません。それと、 for ($i=0; $i<@all_data; $i++){ $work.="$all_data[$i],"; } chop $work; push(@new,$work); }else{ push(@new,$log); } } のところは、 push(@new,join(',',@all_data)); の1行でいいじゃないですか。そうすると $work は不要ですね。 open(IN,"$files2") || &error("$files1を開けません。"); while (<IN>) { ($no,$id,$mail,$type,$data)=split(/,/); &get_date; @logs=(); @new=(); 【1】 open(LOG,"$files1") || &error("$files1を開けません"); @logs = <LOG>; close(LOG); 【2】 foreach $log (@logs){ @all_data = split(/,/,$log); if ($all_data[0] eq $id){ $shori_date="$year\/$w_mon\/$w_mday"; $all_data[33]="($shori_date)($hour:$min)"; 【3】 for ($i=0; $i<@all_data; $i++){ $work.="$all_data[$i],"; } chop $work; push(@new,$work); }else{ push(@new,$log); } } open(ALL,"+< $files1") || &error("$files1に書き込めません"); flock(ALL,2); truncate(ALL,0); seek(ALL,0,0); print ALL @new; close(ALL); 【4】 } close(IN);

kaku-yasu
質問者

お礼

ありがとうございました。おかげで改善できました。 また、わからない事があったら、質問しますので その時は、よろしくお願いします。

その他の回答 (1)

  • okmotokun
  • ベストアンサー率59% (92/155)
回答No.1

上記の書き方だと、$files2 の 1行処理ごとに $work をカラにしないといけません。

kaku-yasu
質問者

補足

アドバイスありがとうございます。 $workをカラにする方法ですが、正規表現の置き換えでもいいのでしょうか? 例えば、$work=~ s/$work//g;で$workの中身をカラにしてもいいのでしょうか? $work=~ s/$work//g;このやり方でやってみたら、日付は入力されましたが、処理が一度しか行われず、 メールの配信が一行目を送って日付を入力したら、スクリプトが終了してしまいました。 どこの部分で、どのようにして$workをカラにすれば全ての送信ファイルを処理できますか? すみませんが教えて下さい。 よろしくお願いします。

関連するQ&A

  • Perlの省略可能な書き方

    open IN,'log.dat'; $_=<IN>; push(@a,$_); この3行を open IN,'log.dat'; push(@a,<IN>); このように2行に書き換えても文法上は問題ないですか?

    • ベストアンサー
    • CGI
  • TSVデータを上書きしたい

    はじめまして。 CGI初心者です。 データの上書きがしたいのですがなかなかうまくいかなくてこまっています。 以下のソースは追加書き込み処理には成功しています。 以下に何を施せば上書きがうまくいくのかアドバイスをお願いします。 $scheduleFile2 = qq($form{"mon"}.tsv); # 読み込み処理 open(LOG,"$scheduleDir/$scheduleFile2"); @logs = <LOG>; close(LOG); foreach $logs(@logs){ ($golfdate,$areada,$ken,$date2,$para)=split(/\t/,$logs); } # 読み込み処理 # 書き込み処理 unless(&serchFile($scheduleDir,$scheduleFile2)){ &makeFile("$scheduleDir/$scheduleFile2"); } @DATA = (); open(FH,"+<$scheduleDir/$scheduleFile2"); flock(FH,LOCK_EX); while(<FH>){ $_ =~ s/\r//g; $_ =~ s/\n//g; # 行の末を削除する chomp; push(@DATA,$_); } $data01 = $form{"code"}.$form{"date"}; $data2 = $form{"area"}; $data3 = $form{"prefecture"}; $data4 = $form{"date"}; $data5 = $form{"open_state"}."\n"; $data = qq($data01\t$data2\t$data3\t$data4\t$data5); print FH "$data"; flock(FH,8); close(FH);

    • 締切済み
    • CGI
  • ログファイルの指定行に書込み

    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<>コメント よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • 書き込み時に勝手にクリアさせない記述

    ログファイルをHTMLにして、 HTMLの中の<!--START-->から<!--END-->に書き込み 処理していくというようなでチャットを作っています。 その中で、書き込み処理の内容を下記のように書いて local($job) = @_; open(IN,"$logfile") || &error("Open Error : $logfile"); @lines = <IN>; close(IN); $i=0; $match=0; @temp=(); foreach (@lines) { chop($_); if ($match) { $i++; push(@temp,"$_\n"); } elsif ($_ eq '<!--START-->') { $match=1; } if ($i > $logs-2 || $_ eq '<!--END-->') { last; } } 記述はこれで間違いないと思ってるのですが 発言フォームでログ数$logsを 選択メニューなどフォームで調整したりすると 書き込むたびに前のログが消えてしまいます。 なぜかわかりません。 どなたか、解決策をご教授お願いします。

    • ベストアンサー
    • 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
  • ログファイルと受信データを比べたい。

    フォームを使用して送られてきたデータをlogを比べて同じものがあったら、同じものがあるということを表示したいのです。 前にも同じようなことをしてできたはずなのですが、なぜかできなくて…。 もうずーっとやっていて頭がボーッとしてきてしまいました。。。。 #フォームで受信したデータ read(STDIN,$buffer,$ENV{'content_length'}); $buffer =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; #ログファイルオープン open FILE,"naisen.log"; @FILES =<FILE>; close FILE; $i=0; $n=0; $gyou = @FILES; #文末の改行を削除 $buffer =~ s/\n$//; $FILES[$i] =~ s/\n$//; foreach(@FILES){ @log = split(/&/,$FILES[$i]); ($keys,$values) = split(/=/,$log[$_]); $FORMS{$keys} = $values; } for ($i=0; $i<=$gyou-1;$i++){ if ($buffer eq $FILES[$i]){ print "$i行目<BR>\n"; } else{ print "$i行目。これはありません。<BR>\n"; print "$FILES[$i]<BR>\n"; print "$buffer<BR>\n"; } } ログの1行目と同じものとときだけ、きちんとした結果がでます。 上記のほかにもいろいろやりましたができませんでした。

    • ベストアンサー
    • CGI
  • perl ファイルのデータを編集したい

    初めまして、perl をやり初めたばかりです。作業は Linux 上で行ってます。 あるテキストファイル data.txt があります。 data.txt の中は、以下のようになっているとします。 100 200 300 400 500 600 これを読み込んで、例えば、 1 2 3 4 5 6 以上の様に各数字を百分の一にして出力したいと思ってます。 一応、色々と調べながらプログラムを書いてはみましたが 思う様に出力されません。以下そのプログラム。 #!/usr/bin/perl open(IN, "data.txt") or die ; @x = <IN>; close (IN); $ref_x = \@x; $n_data = @x; for ($i = 0; $i< $n_data; ++$i) { $$ref_x[$i] /= 100 ; print $x[$i], " "; } print"\n"; どなたか、perl にお詳しい方教えていただけないでしょうか? 宜しくお願い申し上げます。

  • データの入れ替え処理が巧くできないのですが

    いつもお世話になります 簡単なDBを作っているのですが、データの更新処理が巧くいかなくててこずっています POSTメッソドで送られてきた name=actionの内容がedit2、の時 sub menteが実行されます同じく name=noの変数には更新したいファイルの番号がセットされます それらを取得して、ファイルを開き $nooの内容(DBのファイル番号)とnoが一致したらブラウザから送られてきたデータと その部分のデータ($nooはデータの先頭で以降<>で区切って変数が格納される) を入れ替える処理を行いたいのですがどの様に書いたらいいのでしょうか、下記のコードですと変数 $_に更新される前のデータしか代入できず結果ファイルの入れ替えは行えません open(IN,"$logfile") || &error("Open Error : $logfile"); while (<IN>) { ($noo,@arg_[0..$#eqipument],@p[0..5],$n_article,$w_article,@reselect_marks) = split /<>/; if ($no == $noo ) { $_ = join('<>',$noo,(map{$arg_[$_]}(0..$#eqipument)),$p0,$p1,$p2,$p3,$p4,$p5,$n_article,$w_article,@reselect_marks,),'<>',"\n"; } push(@new,$_); } close(IN); # 更新 open(OUT,">$logfile") || &error("Write Error : $logfile"); print OUT @new; close(OUT); 尚ブラウザから送信されてくるデータは以下のような感じです print qq|<form action=\"$myself\" method=\"POST\">\n|; print qq|<input type=hidden name=mode value=\"admin\">\n|; print qq|<input type=hidden name=action value=\"edit2\">\n|; print qq|<input type=hidden name=no value=\"$no\">\n|; 宜しく御教授お願いいたします。

    • ベストアンサー
    • Perl
  • perlでファイルからメールアドレスを抽出

    perlでエラーアドレスを抽出したく いろいろ調べてみましたがどうにもうまくいきません。 主に携帯アドレスが中心ですので RFCに基づいているというよりは簡易な正規表現で、 重複排除くらいはできると理想なのですが 既成で何かいいものはありませんかね? $format='[\w.-]+\@([\w-]+\.)+\w+'; # 簡略なメールアドレス正規表現 open(IN, "エラー.dbx"); foreach(<IN>) { if($_ =~ /($format)/){ push(@emails,$1."\n"); } } close(IN); print @emails; とか open(IN, 'エラー.dbx'); @data = <IN>; close(IN); foreach(@data){ s/ //g; print "$_\n" if /([\w._-]+@[\w._-]+)/ ; } 試してみましたがうまくいきませんでした。

    • ベストアンサー
    • Perl
  • CSVデータの編集の際の重複チェックの方法

    今、data.csv(カンマ区切り)として、左から順位、名前、性別という3項目で、10人程度のリストデータがあります。 data.csv(カンマ区切り)を編集するようにしていますが、順位は重複してはならないので、重複していたらエラーを出したいのですが。。。 ($rank,$name,$sex) = split(/\,/,$line); です。 open(IN,"$logfile") || &error("ファイルが開けません"); @lines = <IN>; close(IN); # 情報の書換え foreach $line (@lines) { ($rank,$name,$sex) = split(/\,/,$line); $line = "$in{'rank'},$name,$sex\n";} push(@new,$line); } # ファイルを更新 open(OUT,">$logfile") || &error("ファイルが開けません"); print OUT @new; close(OUT);

専門家に質問してみよう