- ベストアンサー
perlについて、ファイルへの特定文字列の削除と書き込みについて教えてください
- Perlを使用して、フォームからのデータを受け取り、ファイルに書き込むcgiプログラムを作成したいです。また、特定の文字列がファイルに存在する場合、その行を削除してから書き込む方法を教えてください。
- 具体的には、test.htmlのテキストボックス(name="a_text")に入力された値をx.cgiファイルで受け取り、keep.cgiファイルに書き込むことを考えています。その後、再度テキストボックスの値を受け取り、ファイルに書き込む際に、ファイル内に「a_text」が存在する場合、その行を削除してから2回目の入力値を書き込みたいと思っています。
- ご存知の方、perlについての知識とともに、上記の要件を満たすcgiプログラムの作成方法を教えていただけると助かります。よろしくお願いします。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
> while(<IN>){ > #$workには、keep.txtの、1行目が入っているはず。 > $work=<IN>; <>は、呼び出す度に1行読み込みます。これだと whileの<IN>で $_に keep.txtの1行目が入る → $workの<IN>で, $workに keep.txtの「2行目」が入る → (他に<IN>を使ってなかったとして) whileの<IN>で $_に keep.txtの3行目が入る → $workの<IN>で, $workに keep.txtの「4行目」が入る .... と$workには偶数行しか入りません。 > #書込みする為、keep.txtを書込み用に開く。 > open IN2, "$file2"; 最初、リードでオープンしてるのかと思いました。 $file2に">>"が入っていて、$fileと同じファイルを示している、って、気付きませんでした。 >> を書くならこのopenの中で書いた方が後々のためです。自分で書いたコードも時が経つと忘れます。 また、最近のバージョン(5.6以降)なら、このような2引数版ではなく、3引数以上のopenが推奨です。 open IN, '<', $file ; open IN2, '>>', $file ; また、このopen IN2自体失敗してませんか? keep.txtはすでにリードでオープンされています。それをライトでオープンしようとしたら、失敗するような気がします。 エラーチェックはしましょう。 また、whileで何度もopen IN2が呼ばれます。 最初は成功していたとしても、そのうちopenできるファイル数の限界に達します。 そうでなくても、>>は追記なので、シークして書き込みポイントを変えないかぎ、ファイルの末尾に追加されます。 今は2行読んで1行書いているので終了しますが、ちゃんと1行ずつ読むようにしたら、1行読んだら1行追加されていくので、永遠に(ディスクがいっぱいになるまで)終りません。 方法1) 文字列または文字列のリストとして、Perlに読み込み → 加工 →書き出し open IN, '<', $file ; @line = <IN> ; #全部読み込み close IN ; # 開いたら閉じる ### @lineの加工 ### open OUT, '>', $file ; print OUT join('', @line); close OUT ; # 開いたら閉じる 方法2) 読み書きモード( +< ) でopen → tellで読み出し/書き込み位置を記録 → 読み出し位置へseek → 読み出し → 次行用に読み出し位置を更新 → 加工 → 書き込み → 次行用に書き込み位置を更新 (コードは面倒なので省略) 以上「絶対に同時に使われることが無いことが保証される場合」のやりかたです。 CGIということは、誰が何時使うか不定、ということです。 例えば Aさんがa.htmlからsubmit → keep.txt に保存 →Aさんがb.htmlからsubmit → keep.txt に保存 ならよいのですが Aさんがa.htmlからsubmit → keep.txt に保存 →Bさんがa.htmlからsubmit → keep.txt に保存 →Aさんがb.htmlからsubmit → keep.txt に保存 となったら、最終的にどうなるかよくわかりませんよね? > 通常、複数画面あり(複数のHTMLファイル(form))各画面の値を保持しておく場合、どのような方法がよく、利用されるものなんでしょうか? 常套手段としては ・同じであることを示すIDを用意する。 HTMLも静的なものでなく、CGIで動的に作成するようにして、全てに同一IDを <input type="hiddern" name="ID" value="XXXXXXX"> 等として埋め込んだり、Cookieに書き込んだりする。 CGI側で、IDをチェックして一連の入力か、別の入力かを判定して処理を分ける. ・a.htmlをsubmitしたら、単にメッセージを出すのではなく、submitされた内容をtype=hidden等で引き継いだ b.html 相当のものを動的に作成する。 ・親画面を用意し、 a.html,b.htmlはその子にする。 submitでは直接送信せず親画面にjavascript等で転送。 最終的な送信は最後に親画面からまとめて行う。 等があります。 あとは、あなたのやりたい事次第です。
その他の回答 (1)
- toraneko75
- ベストアンサー率51% (27/52)
該当箇所のHtmlやPerlソースを書いて頂けたら意見も具体的に言いやすいのですが、 もしかすると的外れかもしれないです 最初のa_textを二回目のa_textは一行でということでしょうか? test_htmlのフォームはテキストエリアでということでしょうか? それでしたら、最初のa_textを一旦ファイルに入れておいて、それを開いて例えば$old_textに入れて、 次のa_textを$new_textに入れてtest_htmlのフォームデータを$charactorに入れて $charactor =~ s/$old_text/$new_text/g ; で、変換出来ると思います。
補足
「toraneko75」さん、こんにちわ。ご返信いただきまして、ありがとうございます。 >該当箇所のHtmlやPerlソースを書いて頂けたら意見も具体的に言いやすいのですが、 少し、現状を見ていただけますでしょうか。 _________________________________ 【a.html】 <form method="post" action="keep.cgi" style="background-color:yellow"> A:<input type="text" name="a_text"> <br> <input type="submit" value="送信する"> </form> _________________________________________ _________________________________ 【b.html】 <form method="post" action="keep.cgi" style="background-color:yellow"> B:<input type="text" name="b_text"> <br> <input type="submit" value="送信する"> </form> _________________________________________ 【keep.cgi】 #! c:/perl/bin/perl if($ENV{'REQUEST_METHOD'} eq 'POST') { read(STDIN, $query, $ENV{'CONTENT_LENGTH'}); } else { $query = $ENV{'QUERY_STRING'}; } #$queryに「●_text=●」が入っている。 #ファイルを開く $file = "keep.txt"; $file2= ">>keep.txt"; open IN, "$file" ; while(<IN>){ #$workには、keep.txtの、1行目が入っているはず。 $work=<IN>; #$workに「●_text」があるか、チェックする if($work =~ /$query/){ #ここに、あった場合、その行を削除するコードを書く。 #ファイルの特定の行だけを、削除する方法は、分かりませんが。 } #書込みする為、keep.txtを書込み用に開く。 #$queryには「●_text」が入っているはずなので、ファイルに書込む。 open IN2, "$file2"; print IN2 $query; } close(IN); close(IN2); print "Cotent-type:text/html\pirnt n\n"; print <<EOF; <body bgcolor="pink"> <font size="4" 入力値をファイルに書込みました。<br> </font> EOF exit; _____________________________________ 当初、このように考えていました。 画面を遷移しても、各フォームのテキストボックス入力値を、保持しておく必要があると思い ファイルに書込む事で、入力値を保持すれば良いのではと、考えました。 >次のa_textを$new_textに入れてtest_htmlのフォームデータを$charactorに入れて >$charactor =~ s/$old_text/$new_text/g ; >で、変換出来ると思います。 以前の入力値と、2回目の入力値をそれぞれ変数に保持しておき、上記の方法で変換も試してみたいと 思います。 通常、複数画面あり(複数のHTMLファイル(form))各画面の値を保持しておく場合、どのような方法がよく、利用されるものなんでしょうか? 長くなりまして、申し訳ありません。 以上、宜しくお願いします。
お礼
こんにちわ。ご返信ありがとうございました。 長文にアドバイスいただきまして、ありがとうございました。 参考にさせていただき、もう一度試してみます。