Perl オープン関数について

このQ&Aのポイント
  • Perlのオープン関数についての疑問と、test.cgiとbbstest.cgiの動作の違いについて質問しています。
  • test.cgiとbbstest.cgiで使用されているオープン関数の挙動について疑問があります。
  • test.cgiとbbstest.cgiのオープン関数の使い方に関して、書き込み内容の位置が異なる理由について質問しています。
回答を見る
  • ベストアンサー

Perl オープン関数について

Perl オープン関数について いつもお世話になっております。 オープン関数でわからないことがあるのでご教示お願い致します。 ■test.cgi■ open(FILE, ">sled/$log") or die("error :$!"); eval{ flock(FILE, 2) }; print FILE @DATA; close FILE; ■bbstest.cgi■ open(FILE, ">>sled/$loglog") or die("error :$!"); eval{ flock(FILE, 2) }; print FILE @DATA; close FILE; 上記のtest.cgi側では「>」これが1個で書き込まれるのですが bbstest.cgi側では「>」これ1つだけですと、すべての内容がリセット され、その時入力した内容だけ残ります。 それを「>>」にすると追加はされるのですが、 test.cgi側では 上へ上へと内容は追加されていくのに対し bbstest.cgi側では 下へ下へ追加されていきます。 書込方法は、両方共 unshift(@DATA,"$NO,$tm,$TITLE,$TEXT,$PASS,$IP\n"); このようにしているのですが、 なぜ、同じ処理で、書込方法がかわるのでしょうか? 目的は上へ上へがいいのですが。。。

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

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

  • ベストアンサー
回答No.2

> test.cgiは、事前の@DATAが空なので 上の1-2)の下に下に追加 > bbstest.cgiは、事前の@DATAにデータがあるので、上の 2-1)の上に上に挿入 > の状態なのでしょう。 あっと 失礼いたしました。反対ですね。 test.cgiは 事前に@DATAに既存データが入っていてそれに unshiftで先頭に挿入されているので open の > で 上書きしても上に上にと挿入している状態。 一方 bbstest.cgiは 空の@DATAにunshiftでデータを挿入しているので@DATAには一行ぶんのデータしかないので open で >としたのでは過去データが消えるので open で>> で既存ファイルの最後に 下に下にと 追記している状態。 ということでしょう。

perlhogehoge
質問者

お礼

ありがとうございます! 解決できました!

その他の回答 (1)

回答No.1

問題は unshift(@DATA,"$NO,$tm,$TITLE,$TEXT,$PASS,$IP\n"); とする前の@DATAの中身です。 1) 事前の@DATAが空の状態で unshift(@DATA,"$NO,$tm,$TITLE,$TEXT,$PASS,$IP\n"); とすると、1行しかない@DATAが作られます。 1-1) この状態で open(FILE, ">sled/$log") or die("error :$!"); print FILE @DATA; ↑とすると、これはファイルの上書きなので 元のデータが消えて、1行だけのデータになってしまいます。 1-2) これを、openで >>として open(FILE, ">>sled/$loglog") or die("error :$!"); print FILE @DATA; ↑とすると、既存ファイルの後ろに追記を指定しているので 既存ファイルの最後に1行追加されます。 (下へ下へと追記されるファイル) 2) いっぽう @DATAに、既存のファイル内容が読み込まれた状態で unshift(@DATA,"$NO,$tm,$TITLE,$TEXT,$PASS,$IP\n"); とすると、既存ファイルの内容の前に、一行が挿入された@DATAが作られます 2-1) この状態で open(FILE, ">sled/$log") or die("error :$!"); print FILE @DATA; ↑とすると、これは既存データの”上”に追加されたファイルが作られます。 (上へ上へ挿入) 2-2) open(FILE, ">>sled/$loglog") or die("error :$!"); print FILE @DATA; ↑とすると、既存ファイルの後ろに追記なので 既存データ+追加される1行+もう一度既存データ と多重データになってしまいます。 たぶん test.cgiは、事前の@DATAが空なので 上の1-2)の下に下に追加 bbstest.cgiは、事前の@DATAにデータがあるので、上の 2-1)の上に上に挿入 の状態なのでしょう。

perlhogehoge
質問者

お礼

ありがとうございます! 解決できました!

関連するQ&A

  • PERL カンマ区切り 一致行削除

    教えてくださいm(_ _)m 最初に目的を書きます・・・ ~test.txt~ 1,aaa,eee,ttt 3,eee,eee,yyy 5,ttt,yyy,eee 2,yyy,bbb,qqq ↓ 5,ttt,yyy,eee 2,yyy,bbb,qqq ~~~~~~~~~~ 例1)、カンマ区切り3列目が「eee」 の行を全て削除(完全一致) 例2)、カンマ区切り3列目が「e」を含む 行を全て削除(部分一致) というふうにしたいのですが、 どのようにするのかわからないです・・・ 現在下記のように とりあえず1行目(0番目)を削除するとこまできました。 #! /usr/bin/perl $TEST = 'test.txt'; open(FILE, "<$TEST"); eval{ flock(FILE, 1) }; @DATA = <FILE>; close FILE; $NO = 0; splice @DATA, $NO, 1; open(FILE, ">$TEST"); eval{ flock(FILE, 2) }; print FILE @DATA; close FILE;

    • ベストアンサー
    • Perl
  • open() で開くだけで破損するか

    open(DB,"$file") ;でデータを開くだけでデータが破損することはありますか? たとえば open(DB,"$file") ; flock(DB,2); @lines = <DB>; close(DB); flock(DB,8); のように@linesにデータを格納します。 $fileに上書きはしません。 上記ファイル操作だけで、同時接続があったときにファイルが破損することはありますか? ファイルロック関数を付けた方がいいですか?

  • Perl 処理速度について

    ブログを作成し、カテゴリー別に分けたく下記のようなソースを 書きました。 sub category1 { open(FILE, "<$FILE") or die("error :$!"); eval{ flock(FILE, 1) }; @DATA = <FILE>; close FILE; $a = 0; my @category1 = grep(/,1,/, @DATA); while (<@category1>) { $a++; } &buffer(); if($start > @DATA) {$start = @DATA;} $next = $start + 100; $back = $start - 100; if ($back < 0) { $back = 0; } for ($i=$start;$i<$next;$i++){ last if ($i > @category1); $data = $category1[$i]; &page(); } } これの処理速度が遅いのですが、なにか原因はありますでしょうか? 似たような処理で下記のソースの方が、読み込む内容としては多いのですが、 こちらは普通の速度です。 sub diary2017 { open(FILE, "<diary/diary-2017.txt") or die("error :$!"); eval{ flock(FILE, 1) }; @DATA = <FILE>; close FILE; &buffer(); if($start > @DATA) {$start = @DATA;} $next = $start + 1000; $back = $start - 1000; if ($back < 0) { $back = 0; } for ($i=$start;$i<$next;$i++){ last if ($i > @DATA); $data = $DATA[$i]; &page(); } } カテゴリーのサブルーチンとアーカイブ専用のサブルーチンで違う点といえば $a = 0; my @category1 = grep(/,1,/, @DATA); while (<@category1>) { $a++; } このgrepのとこですが、 これが遅いとすると対処方法はありますか? ※開くファイルはアーカイブは直接名前にしてて、カテゴリーは変数を使ってますが  これは同じです。

    • ベストアンサー
    • Perl
  • mac で perl  open関数について

    お世話になります。 現在、perlの勉強中です。 状況は mac osx 10.6.6です。 使用参考書は「perl言語プログラミングレッスン[入門編]」です。 CGIは関係なしで行っております。 open関数について参考書を読みながら、 勉強をしているのですが、openでファイルをオープンするときについてなのですが、 参考書上では、「関数openは、指定されたファイル名を持つファイルをハードディスクから探し出し、オープンしようと試みます」と言う説明があるのですが、 今現在、試している文例では、特定の場所にファイルがあるときでないと、 オープンしてくれません。 文例は [test.pl] use strict; use warnings; my $filename = 'file.txt'; open(FILE, $filename) or die "$filename: $!"; while (my $line = <FILE>){ $line =~ s/ /_/g; print $line; } close(FILE); という形で、ファイルの " " (スペース)を抜き出して "_" (アンダースコア)に置き換えるという設問です。 ただ、現況は                  /Users/(myname)/Documents/test/test.pl #(myname)は私の名前のフォルダです。 にあるコードをターミナル上で実行すると、 /Users/(myname)/file.txt に配置しているときしか、読み込んでくれません。 そこから、ファイルを移動させてしまうと、 読み込んでくれないのです。 そこで、ご質問ですが、 1 「関数openは、指定されたファイル名を持つファイルをハードディスクから探し出し、オープンしようと試みます」 と参考書に記載がありましたが、実際には探し出しはしてくれないのでしょうか? それとも、自分のパソコン、コードに問題があるのでしょうか? 2 自分が指定した場所にあるファイルをオープンするには どのようにすればよいでしょうか? ターミナルで指示するのか、それともコードに加えるべきか、 ご指示くださいませ。 また、詳しい方がおられましたら、 お答えいただければと思います。 それでは失礼します。

    • ベストアンサー
    • Perl
  • Perl BBS掲示板 サーバ側のファイル削除

    いつもお世話になっております。 サーバ側のファイルを削除したいのですが、 どのようにすればいいのでしょうか・・・? #-----------------------------------------DELETE sub deletedata { use CGI; my $form = new CGI; my $tm = time; my $DELETE = $form->param('pass'); my $NO = $form->param('no'); my $NAME = TransFormdata($form->param('name')); my $TITLE = TransFormdata($form->param('title')); my $TEXT = TransFormdata($form->param('text')); my $img = TransFormdata($form->param('img')); open(FILE, "<$FILE") or die("error :$!"); eval{ flock(FILE, 1) }; @DATA = <FILE>; close FILE; my $DELETE = $form->param('pass'); my $NO = $form->param('no'); if(length $NO == 0) {} elsif($DELETE eq $PASSWORD) { deleteImg($NO); splice @DATA, $NO, 1; } else{} open(FILE, ">$FILE") or die("error :$!"); eval{ flock(FILE, 2) }; print FILE @DATA; close FILE; &endform } #-----------------------------------------DELETE #-----------------------------------------UPFILEDELETE sub deleteImg { my ($NO,$tm,$NAME,$TITLE,$TEXT,$imgname) = split(/,/, $DATA[$_[0]]); $filename = $DIR . $imgname; if(-e $imgname) { unlink $filename; } } #-----------------------------------------UPFILEDELETE ラジオボタン選択 ↓ パスワード入力 ↓ 削除ボタン ↓ 削除 この段階で テキストファイルの指定行は削除されているのですが、 画像が投稿され、サーバー側に残っているファイルも削除させたいのです。 Unlinkを使うとなっていたのですが・・・わからないです。 どうかご教示お願い致しますm(;;)m

    • ベストアンサー
    • Perl
  • perlにてスペースの削除に苦労してます。

    perlにてテキスト書き出しをしをしたとき 書き出したテキストファイルの先頭にどうしてもスペースが入ってしまうので そのテキストを別のcgiにて読み込み表示するときに 先頭のスペースを削除しようとしていますがうまく行きません 多分スペースをパターンマッチさせるのだろうと思うのですが いまいち私の理解が足らないようでぜひどなたか教えてください。 (1つ目のcgi)------------------------------- フォームから入力$title $subtitle $contentsとしそれを下記のような形で読み込み(途中省略) use CGI; $query = new CGI; $title = $query->param('title'); $subtitle = $query->param('subtitle'); $content = $query->param('content'); #タブ区切りにし@memoryに代入 @memory="$meday\t$title\t$subtitle\t$content\t$number\t$namberc\n"; open(FILE,">>../data/memory.txt")||&error("$datafile 外部ファイルが開きませんでしたエラー"); print FILE"@memory"; close(FILE); ----------------------------- それを違うcgiのソースで読み込み------------------------------------ (2つ目のcgi) open(IN, "< sys/data/memory.txt"); eval{flock(IN,1)}; @inbun=<IN>; for($i=0;$i<@inbun;$i++){ @retudata=split(/\t/,$inbun[$i]); $inbun[$i] =~ s/^\s+//g; $retu =~ s/^\s+//g; @retudata[$i]='$retu[0]\t$retu[1]\t$retu[2]\t$retu[3]\t$retu[4]\t$retu[5]\n'; ; }@data=@inbun; open(FILE,">sys/data/memory.txt")||&error("../data/memory.txt 外部ファイルが開きませんでしたエラー"); print FILE"@data"; close(FILE); close (IN); --------------------------------------------------- 追加するとなぜか先頭にスペースが入りどうしてもとれないんですが どうしたら良いでしょうか? ちなみに結果は下記のとおりです。 20121122 test1 test1 test1あいうえおABCDEFG 1 112223157 20121122 test2-r test2-r test2-rあいうえおABCDEFG 2 1122231647 20121122 test3 test3 test3あいうえおABCDEFG 3 112223254 乱筆乱文ご容赦ください。 宜しくお願いします。

    • ベストアンサー
    • Perl
  • open中のファイルをrename

    オープン中のファイルをflockによる排他をしたままrenameしたいのですがどうもうまくいきません。 sysopen(LOCK, "$file", O_WRONLY);   もしくは open(LOCK, "> $file"); flock(LOCK, 2); rename($tempfile,$file); close; close前にrenameするとロックが外れてしまいます。 close後にrenameをするとやはりロックが外れた状態でのrenameになります。 renameするファイル以外にflock専用ファイルを固定で一つ用意すれば簡単なのですが openしたいファイル数は相当な数があり、各ファイルごとにロックをかけたいのです。 全ファイル分のflock専用ファイルを用意するか、排他方式をmkdirにする以外 何か良い手立てはございますでしょうか。

  • Perlのtruncateについて

    + test.txt 0 1 2 3 + main.cgi open(FH, "+<test.txt"); my @Log = <FH>; truncate(FH, 0); seek($FileHandle, 0, 0); print(FH "4"); close(FH); これで、main.cgiを実行すると、test.txtの中身は 4 1 2 3 となってしまいます。truncateがきいてないようなのですが、なぜでしょうか。 truncate(FH, 0) or die "error"; とすると、errorと表示されてしまいます。 なぜこうなるのでしょうか。 致命的エラーがでるわけでもないので、環境が悪いわけではないような気がするのですが。 flockをしたいのですが、他にファイルの中身を空にする方法とかありませんか。

    • ベストアンサー
    • Perl
  • perlで検索 カンマ n番目

    ~log.txt~ 1,a,w,e,r 2,a,w,e,r 2,e,a,v,ssss 3,s,ssss,a,a $FILE = 'log.txt'; $Search = 'sss'; ~Search.pl~ open(FILE, "<$FILE") or die("error :$!"); eval{ flock(FILE, 1) }; @DATA = <FILE>; close FILE; $a = 0; my @Search = grep(/$Search,/, @DATA); while (<@Search>) { $a++; } print "@Search\n"; このようなデータで 検索ワード=sssのとき ヒットするのが 2,e,a,v,ssss 3,s,ssss,a,a [0][1][2][3][4] この2つです。 ここまではいいのですが、 2番目のsssのみを取り出したいとき my @Search = grep(/$Search,/, @DATA); ここをどのように変えればいいのでしょうか・・・?

    • ベストアンサー
    • Perl
  • Perl 教えてください。

    下記のような簡単なスクリプトなんですが、なぜかサーバーにアップすると動きません。 ローカルでコマンドプロンプトから直接実行するとまともに動作します。 パーミッションは「755」と「705」でやってみましたが。 perlのパスは合っていますし、実際同じ場所に置いた他のCGIは動作します。 #!/usr/bin/perl open (DT, "<./data/***/***.csv") or die "File '***.csv' Open Error."; @data = <DT>; $data[0] = ",,,,,,\n"; open (OUT,">./data/***/***1.csv") or die "File '***1.csv' Open Error."; print OUT @data; close (DT); close (OUT); 原因が分からず困っています。 解決策でなく、原因と思えるだけの回答で結構ですので何卒よろしくお願いいたします。

    • ベストアンサー
    • Perl

専門家に質問してみよう