ログファイルに指定行または指定場所での書き込み方法

このQ&Aのポイント
  • 指定行または指定場所に書き込むためのログファイルのスクリプトを変更する方法はありますか?
  • dat.cgiファイルに指定行または指定場所で書き込む方法を教えてください。
  • ログファイルの特定の行数または文字列の間に書き込むためのスクリプトの変更方法を教えてください。
回答を見る
  • ベストアンサー

指定行に書込み

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行目に書き出す。 または、 ・指定された文字列の間に書き出す。 (例)<!--開始-->ここに書き出す。<!--終了--> このどちらかが出来ればいいのですが、上記スクリプトをどのように変更すれば可能になるでしょうか?お手数ですが、どうぞ宜しくお願いいたします。

  • MKNET
  • お礼率94% (89/94)
  • Perl
  • 回答数4
  • ありがとう数3

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

  • ベストアンサー
  • kumoz
  • ベストアンサー率64% (120/185)
回答No.4

たぶん、大丈夫だと思います。というのも、私自身は File::Copy を使ったことがなく、「プログラミング Perl」を読んで確認した次第です。 copy の場合も、open や close と同様に後ろに or die ... を付けることを お勧めします。こうすると、失敗したときに有益な情報が得ることができます。

MKNET
質問者

補足

or dieを付けて完成させました。いろいろとご指導頂き誠に有難うございました。m(__)m

その他の回答 (3)

  • kumoz
  • ベストアンサー率64% (120/185)
回答No.3

実際のファイルの内容とは違うでしょうが、log.cgi と dat.cgi は次のようにしています。 log.cgi aaa<>bbb<>ccc<>ddd bbb<>ccc<>ddd<>eee ccc<>ddd<>eee<>fff ddd<>eee<>fff<>ggg eee<>fff<>ggg<>hhh fff<>ggg<>hhh<>iii ggg<>hhh<>iii<>jjj dat.cgi <><> <><> <><> <><> <><> スクリプトは、なるべく元のコードを使っています。 なお open と close は、失敗したときのために die を付け加えました。 open(IN, "log.cgi") or die "Can't open log.cgi: $!"; @f_data = <IN>; close(IN) or die "Can't close log.cgi: $!"; $i = 1; open(FILE, "dat.cgi") or die "Can't open dat.cgi: $!"; open(OUT, ">new_dat.cgi") or die "Can't open new_dat.cgi: $!"; select OUT; while ($line = <FILE>) { if ($. == 3) { print "<>"; foreach (@f_data) { if ($i > 5) { last; } ($f_data1, $f_data2, $f_data3, $f_data4) = split(/<>/); print "$f_data1"; $i++; } print "<>\n"; } else { print $line; } } select STDOUT; close(FILE) or die "Can't close dat.cgi: $!"; close(OUT) or die "Can't close new_dat.cgi: $!"; このスクリプトを実行すると、new_dat.cgi の内容は次のようになります。 <><> <><> <>aaabbbcccdddeee<> <><> <><>

MKNET
質問者

お礼

何度もお手数をおかけいたしました。本当に有難うございます。おかげ様で解決することができました。 ちなみに、new_dat.cgiに書き出された内容を、dat.cgiに反映させるために以下のものを「close(OUT) or die "Can't close new_dat.cgi: $!";」の下の行に追加してみました。いつも改造するときは余りわからず適当に考え付いた機能を追加していっているため、これでいいのかあまり自信がありません。これで問題ありませんでしょうか。宜しければご確認いただければ幸いです。 use File::Copy; $data = 'data.cgi'; $newdata = 'new_data.cgi'; copy( "$newdata", $data );

  • kumoz
  • ベストアンサー率64% (120/185)
回答No.2

別のファイルに出力する方法です。 open(FILE, "dat.cgi"); open(OUT, ">new_dat.cgi"); while ($line = <FILE>) { if (cond) { # 条件に合う行であれば、新たな出力をここに書く } else { print OUT $line; # 変更の必要のない行をそのまま出力 } } .... while ループで dat.cgi を1行ずつ読み込んで、目的の行を探します。 100 行目であれば、cond のところを $. == 100 とします。 別ファイルに出力すれば、dat.cgi はそのままにスクリプトを直して 実行するたびに、新たに new_dat.cgi 作り直してくれます。 ファイルの中身を確認しながら、頑張ってみてください。

MKNET
質問者

お礼

有難うございます。教えていただいた内容で以下の処理のスクリプトを改造しようと何度も試みてみましたが、素人のため、思ったようになかなか動作させることができません。大変お手数ですが、以下スクリプトで教えていただいた内容の動作をさせるにはどのように以下スクリプトを書き直せばよろしいのでしょうか?宜しくお願いいたします。 open( IN, "log.cgi" ); @f_data = <IN>; close( IN ); $i = '1'; #書き出し先ファイルをオープン open( OUT, ">dat.cgi" ); select OUT; foreach( @f_data ){ #5行超えたら処理を抜ける if( $i > 5 ){ last; } #一行の内容を<>で分割して、先頭4つを変数に取る ( $f_data1, $f_data2, $f_data3, $f_data4 ) = split( /<>/ ); #1つ目を書き出す print "$f_data1"; $i++; } #書き出し先ファイルを閉じる select STDOUT; close( OUT );

  • kumoz
  • ベストアンサー率64% (120/185)
回答No.1

質問以前の問題として、 open(OUT, ">dat.cgi"); のように書くと、dat.cgi の内容はすべて捨てられてしまいます。 肝心の質問の方ですが、できないというのが回答になると思います。 出力ファイルハンドルを通して、任意の行に書き出したり、 挿入することはできません。これを行うには一度入力用にファイルを オープンし、配列などに格納して加工してから、ファイルを出力用に 再オープンして書き出す、という作業が必要です。 open(FILE, "dat.cgi"); @file = <FILE>; @file を加工 open(FILE, ">dat.cgi"); @file を出力

MKNET
質問者

お礼

参考意見をありがとうございます。 > のように書くと、dat.cgi の内容はすべて捨てられてしまいます。 そうですね。そのようになるように現在は使われています。 この現在使われてるスクリプトで上記質問内容の事を行うには、どのように書き直せばよいのか知りたいため質問させていただきました。 Perlは勉強しはじめの素人のため、何となくできそうかなと自分なりにも試行錯誤しておりましたが、かなりの改造をしないと上記内容は難しいということになるのでしょうか?もう少し自分なりにも工夫してみて、その間に改造できるという回答が得られないようでしたら諦めることにします。

MKNET
質問者

補足

dat.cgiの中身を以下のようにすれば、上記質問内容は実現可能でしょうか? ---------------------------------- 1<><> 2<><> 3<><> 4<><> 5<><> ---------------------------------- log.cgiの$f_data1の部分を3行目の2番目に書き出す。 ---------------------------------- 1<><> 2<><> 3<>ここに書き出す。<> 4<><> 5<><> ---------------------------------- このような方法でなら可能ではないでしょうか?で、自分なりにこの方法で試行錯誤していましたが、やはり私の知識ではなかなか書けそうにありません。どなたかお力をお貸しいただけないでしょうか。宜しくお願いいたします。

関連するQ&A

  • 全行読み込むには

    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
  • UTF-8に変換

    open( IN, "data.cgi" ); @f_data = <IN>; close( IN ); $i = '1'; open( OUT, ">log.cgi" ); select OUT; foreach( @f_data ){ if( $i > 10 ){ last; } ( $f_data1, $f_data2, $f_data3, $f_data4 ) = split( /<>/ ); $f_data1 =~ s/ //g; print "$f_data1階 $f_data4\n"; $i++; } #書き出し先ファイルを閉じる select STDOUT; close( OUT ); 上記スクリプトでlog.cgiに書き出される文字コードをUTF-8に変換したいのですが、いろいろな解説サイトの説明通りに行うと、私のやり方が間違っているだけだと思いますが、サーバエラーになっていまいます。サーバはxrea.comを利用しております。 data.cgiの文字コードはSJISです。 上記スクリプトの場合は、どのように変更すればよろしいのでしょうか?宜しくお願いいたします。

    • ベストアンサー
    • Perl
  • ログファイルの指定行に書込み

    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
  • 文字列の抽出

    指定したファイルの中から'<'と'>'とで囲まれた部分文字列を抽出したいのですが方法がわかりません。どのようにしたらできるでしょうか? *ファイルは制御コードが混じっているのでバイナリとして扱わないといけないかもしれません。 よろしくお願い致します。 ------------------------------------------------- open(IN, "test.dat"); open(OUT, "> out.txt"); binmode(IN); while (<IN>) { /^<(\w+)>$/; print OUT "$1\n"; } close(IN); close(OUT);

    • ベストアンサー
    • Perl
  • 配列のデータから改行だけを取り除いて上書きしたい

    いつもお世話になっています。 CGIで現在下記のようなファイルがあります。 【sample.cgi】 1<>2<>3<>4<>5<> 6<>7<> これを下記のスクリプトで呼び出し配列に入れます。open(IN,"./sample.cgi"); @DATA = <IN>; close(IN); @data = split(/<>/,$DATA[0]); @N_DATA=(); unshift(@N_DATA,"$data[1]<>$data[2]<>$data[3]<>$data[4]<>$data[5]<>$data[6]<>$data[7]<>"); open(OUT,">./sample.cgi") or &error('書き込み失敗'); print OUT @N_DATA; close(OUT); しかし実行結果は改行が残ったままで、どうにか 1<>2<>3<>4<>5<>6<>7<> という形で出力したいのですがどのように変更を行えば宜しいでしょうか。 恐らく「unshift」の部分が行を追加していっていると思うのですが、printなどで出力するとsample.cgiの中身が空になってしまい・・・。 「読み込むデータに改行があった場合は改行を削除して読み込む」という動作をさせたいのですが・・・。 何卒よろしくお願い致します。

    • ベストアンサー
    • CGI
  • データからある文字列の次の行を出力するには

    perlの初心者です。はじめまして。 質問タイトルそのままなのですが、データからある文字列の次の行を出力するにはどのような記述をすればよろしいでしょうか?よろしくお願いします。 ・データは1ファイルで2000あります。1つのデータは[X,Y]で始まり、次の[X,Y]の前までになります。 ・出力はCSVファイル。 ・DAT errがあった場合はその次の行を出力。なかったら、DAT列は空白にする。 #!/bin/perl open(FILE,"<$ARGV[0]"); open(OUT,">$ARGV[0].csv"); ########################## err count ########################### print OUT "X,Y,NUMBER,DAT,\n"; while(<LOG>){ if($_ =~ /X=(.+)\,Y=(.+)/){ chomp($_); print OUT "\n$1,$2,"; } if($_ =~ /NUMBER (.+)/){ print OUT "$1,"; } if($_ =~ /DAT err/){ print OUT "PASS,0,"; } } close(OUT);

    • ベストアンサー
    • Perl
  • 半自作cgiが思うように動作しません。

    HTMLページから、$Dataというファイル名を持って来て、 このcgiで、$Data.jpgとなり、 その画像を、新しいウインドウ(サイズ指定)で表示させたいのです。。。 このcgiで新しくウインドウを開き、何かしらをクリックさせてから、サイズ指定のウインドウで画像を表示させるのはできるのですが、 クリックさせずに、しかも、最初に開いたウインドウは勝手に閉じさせたいのですが、 どこをどう直せばいいのでしょうか? #! /usr/bin/perl print "Content-type: text/html\n\n"; $Data = $ENV{'QUERY_STRING'}; $tail = ".jpg"; &header; print "<SCRIPT LANGUAGE='JavaScript'>\n"; print "function newwindow(imgurl) {\n"; print "nwin = window.open('img/$Data$tail\', 'Newwindow','width=300,height=210');\n"; print "nwin.document.open();\n"; print "nwin.document.write(\"<html><head>\")\; \n"; print "nwin.document.write(\"</head><body><img src=\"img/$Data$tail\'>\")\;\n"; print "nwin.document.write(\"<br><INPUT type='BUTTON' value='CLOSE' onclick='window.close()'>\")\; \n"; print "nwin.document.write(\"</body></html>\"); \n"; print "nwin.document.close()\;\n"; print "return false;\n"; print "}\n"; print "</SCRIPT>\n"; print "<BODY onload='window.close()'></body></html>\n"; sub header { print <<"EOM"; <html> <head> <META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=Shift_JIS"> <title>$Data</title> </head> EOM }

    • ベストアンサー
    • CGI
  • 指定したフォルダにアップロード

    Perlを使用してアップローダーを作成しました。 今までは # 受信データを書き込む open OUT,">$fnme"; binmode OUT; print OUT $in{'upfile'}; close OUT; としていたんですが、これではファイル数が多くなった時にエライことになるので、ディレクトリを作成してその中に…と思いまして。 で、ディレクトリをオープンが opendir DIR, "$folder_name"; ということはわかったのですが、 これを上記と組み合わせるにはどうしたらいいのでしょうか? ためしに opendir DIR, "$folder_name"; open OUT, ">$fnme"; binmode OUT; print OUT $in{'upfile'}; close OUT; closedir folder; としてみましたが、普通にcgiがあるフォルダにアップロードされてしまいました(^^; ディレクトリの中のファイル名を取得とかはあったんですが、指定のフォルダにアップロード、が見つからなくて…。

    • ベストアンサー
    • Perl
  • 連続投票の制限

    投票cgiを設置したいのですがうまくいきません、集計を1日一回だったのを少し改造して即時集計にしました 一応動くのですが、連続投票できてしまいます。 連続投票を一定時間制限できるようにしたいのですがうまくいきません 60秒くらい間をおいてから投票できるようにできますか? ip制限もあるみたいなのですがこれも機能してないです・・・ 改善できるなら元のソースがかなり変わってもかまいません 連続投票制限だけでも機能できればと思っています。よろしくお願いします local $times = time(); sub vote{ if($FORM{id}){ my $fl=0; if(!$CK_ref){$fl=1;} else{ if(index($ENV{'HTTP_REFERER'},index.html>=0){$fl=1;} } if($fl){ $FORM{id}=~s/\n//g; my $vote = $FORM{vt2}?1:0; open(OUT,">>vote_temp.cgi"); #時間用のログファイルに書き込み print OUT "$FORM{id}<>$ENV{'REMOTE_ADDR'}<>$FORM{vt}<>$vote<>".$times."<>\n"; close(OUT); &reset_vote if $VT_RESET < $times; my(@log_lines,%pt,%pt2,%cnt,$name,$value,%CKIP); open(IN,"vote_temp.cgi"); my @log = <IN>; close(IN); if(@log){ my $cktime = $times - 60; #60秒制限 open(IN,"vote_ck_IP.cgi"); #投票した人のIPを記録したログ while(<IN>){ my @ck = split('<>'); next if $_[1] < $cktime; $CKIP{$_[0]} = $_[1]; } close(IN); foreach(@log){ chop; my @rank = split('<>'); #ID<>IP<>評価<>おすすめ<>時間\n next if $CKIP{"$rank[0]_$rank[1]"}; $pt{$rank[0].'_'.$rank[2]}++; $pt2{$rank[0]}++ if $rank[3]; $cnt{$rank[0]}++; $CKIP{"$rank[0]_$rank[1]"} = $rank[4]; } open(OUT,">vote_temp.cgi"); close(OUT); open(OUT,">vote_ck_IP.cgi"); while(($name, $value) = each(%CKIP)){ print OUT "$name<>$value<>\n"; } close(OUT); open(IN,"log.cgi"); my @data = <IN>; close(IN); foreach(@data){ #集計処理長かったので省略 } open(OUT,">vote_bf.cgi"); open(IN,"vote_log.cgi"); while(<IN>){ print OUT $_; } close(IN); close(OUT); open(OUT,">vote_log.cgi"); print OUT @log_lines; print OUT "\n1;\n"; close(OUT); } &make_vote_ck('set'); } } sub reset_vote{ my @log; foreach my $i(1..$LAST_ID){ next if !@{$VT[$i]}; $VT[$i][18] = $VT[$i][7]; $VT[$i][19] = $VT[$i][8]; $VT[$i][20] = $VT[$i][0]; foreach my $j(0..8){ $VT[$i][$j] = 0; } push(@log,'$VT['.$i.'] = ['.(join(',',@{$VT[$i]}))."];\n"); } open(OUT,">vote_log.cgi"); print OUT @log; print OUT "\n1;\n"; close(OUT); &make_vote_ck('reset'); } sub make_vote_ck{ if($_[0] eq 'set'){ my @t =localtime($times + 86400); $VT_TIME = timelocal(0,0,5,$t[3],$t[4],$t[5]); $VT_RANK = $VT_RUI = $VT_RECO = $VT_RCRUI = $VT_COUNT = $VT_CTRUI = $VRK_CK = 1; } if($_[0] eq 'reset'){ my @m =localtime($times); $m[4] += 1; if($m[4] > 12){ $m[4] = 1; $m[5] += 1; } $VT_RESET = timelocal(0,0,2,1,$m[4],$m[5]); $VT_RANK = $VT_RECO = $VRK_RS = $VRK_CK = 1; } if($_[0] eq 'restore'){ $VT_RANK = $VT_RUI = $VT_RCRUI = $VT_RECO = $VT_COUNT = $VT_CTRUI = $VRK_CK = 1; } open(OUT,">vote_ck.cgi"); print OUT "\$VT_TIME = '".$VT_TIME. "';\n"; print OUT "\$VT_RESET = '".$VT_RESET. "';\n"; print OUT "\$VT_RANK = '".$VT_RANK. "';\n"; print OUT "\$VT_RUI = '".$VT_RUI. "';\n"; print OUT "\$VT_RECO = '".$VT_RECO. "';\n"; print OUT "\$VT_RCRUI = '".$VT_RCRUI. "';\n"; print OUT "\$VT_COUNT = '".$VT_COUNT. "';\n"; print OUT "\$VT_CTRUI = '".$VT_CTRUI. "';\n"; print OUT "\$VRK_CK = '".$VRK_CK. "';\n"; print OUT "\$VRK_RS = '".$VRK_RS. "';\n"; print OUT "\$LAST_ID = '".$LAST_ID. "';\n"; print OUT "\n1;\n"; close(OUT); }

    • ベストアンサー
    • Perl
  • アクセスカウンタでリロード時のカウントされるのをやめたい!

    自分のPCでIIS5.0をインストールして CGIの作成練習をしています。 簡単なアクセスカウンタを作ったのですが、 どっかのをコピーしただけ。。。 sub counter{ #(読込み) open (IN,"<./count.dat"); $raikyaku = <IN>; close (IN); $raikyaku++; #(書き込み) open (OUT,">./count.dat"); print OUT $raikyaku; close (OUT); } これを、更新ボタンを押した時にカウントされない ようにしたいです。 また、BBSに埋め込もうと思っているので、 投稿ボタンで再表示された場合も カウントされてほしくありません。

専門家に質問してみよう