重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

【GOLF me!】初月無料お試し

perlについて、教えてください。

「apple.html」と「bigin.html」に、それぞれ,
textboxが一つあり、入力値をkeep.cgiで受取り、
「keep.txt」に書込もうと考えています。

a.htmlのテキストボックスに、入力して、submitボタンをクリック
しても、「keep.txt」に何も書き込まれません。


「keep.txt」に、
_______
a=100
b=200
________
のように、書込みたいと考えています。


下記、keep.cgiのどこが間違っているのか、教えてください。

___以下、「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=●」が入っている。

#ファイルを開く、読み書き用。
$open_file_name = "+<keep.txt";

open(A,$open_file_name);

#開いたファイルを、1行ずつ読み込む。
while(<A>){
#$_には、keep.txtの、1行目が入っている。
#$_(読込んだ行)に「●_text」があるか、チェックする
if($_ =~ /$query/){
#あった場合
next;
}
#読込んだ行に、$query以外なら、配列に。
@keep = $_;
@keep = $query
}

#ファイルを閉じる。
close(A);

#ファイルを削除する
unlink($open_file_name);

#削除したのと、同じファイル名で新規作成
$new_file = ">>keep.txt";
open(A,$new_file);

#再度、作成したファイルに、配列@keepを書込む。
print A @keep;

#ファイルを閉じる
close(A);


print "Cotent-type:text/html\pirnt n\n";

print <<EOF;

<body bgcolor="pink">
<font size="4">
入力値をファイルに書込みました。<br>
</font>

EOF

exit;
______________________

宜しくお願いします。

A 回答 (3件)

間違っている点



1.受信データをベタのまま使用している
  たぶん学校の課題かなにかでしょうが、この状況では練習問題にもなりません。
  POSTやGETのメソッドで受信したデータは名前と値にそれぞれ分離して扱いましょう。
  現状ではボタンもフォームの一部なのでボタンデータの値(例:BT1=送信など)も受信文字列に入っているはずです。
  それをそのまま正規表現でパターンマッチをとっても無意味でしょう。
  さらに、エンコードされている可能性も考慮してデコード処理も必要でしょう。
  連想配列に代入して処理するのが一般的です。

2.ファイルを開く
  書きこみの必要性がないなら出来るだけ「読み込み」だけで処理することです。
  データ量にもよりますが「ファイルを開いている状況は出来るだけ短時間に押さえる」ように処理するのが吉です。
  この場合データ量が少ないので、一気呵成に配列へ読み込んでファイルはさっさと閉じましょう。
  配列のループで処理すればいいのです

3.ファイルを削除
  オリジナルデータは出来るだけ残すようにする。
  HDDの空き容量が問題にもなりますが、ここはunlinkよりもrenameを使って以前のデータを残すべきでしょう。
  いまどきのマシンでテキストデータが圧迫するようなマシンならサーバなんぞには向いていません。

4.書き込み処理
  状況にもよりますが、前の回答者様が述べているようにファイルのブロック処理があったほうがいいでしょう。
  ただし、シェバングをみるとWindows上で組んでいるようなのでPerlのファイルロックはあてにできません。
  CGIでは古典的手法なのですが、外部ファイルのステータスを利用するなど、裏技を利用するのが良いでしょう。
  「perl」「ファイルロック」などでググれば見つかるでしょう。
  また出力データは丁寧に出しましょう。配列をベタでガバーではまともに処理ができていてもいなくても消された元ファイルは成仏できません。
  せっかく出力イメージを提示しているのですからそのように出力するよう少しは努力してください。


5.メインの処理の部分
  正直、結果の部分とプログラムの内容があまりに乖離しすぎていて、どんな処理をしたいのかが汲み取れないので以下の点を明確にしてください
  ・受信データとファイルデータを比較しているが左辺が同一のデータ部分だけを上書きするような仕組みなのでしょうか?
  ・フォームに入力値がなかった場合の処理は必要ないのか?→必要ないなら比較などせずにマルマル上書きすれば済む話ですよね。

追伸:
 まえの質問でも同じなんですが回答を受け取ったあとそこで生じた問題をその1時間後に別のスレで質問していましたが、そういう丸投げの姿勢では技術は身につきません。
 アドバイスするくらいのスペースしか有りませんので、アドバイスが可能なようにご自身で多少でも努力されるようお願いします。
 こうしたくてこうしましたがダメでした的な状況でのアドバイスなら回答ももう少し具体的かつ明確になるでしょう。
    • good
    • 0

前のもそうなんですが、やりたいことを、もう少し一般的に書けませんか?


queryは a_text= / b_text= で、それを加工している様子はないのに、出力は a= / b= になっています。
あと、消すっていってる意味もよくわかりません。
a=~は最後に送られた a_text=の中身になるように、最新に書き換えていく、ということでよろしいのでしょうか?


> #読込んだ行に、$query以外なら、配列に。
> @keep = $_;
> @keep = $query
配列になってないし、追加にもなってません。
配列に入らなければ、当然出力もされません。

配列については、解説書や解説サイトで1章さいて説明してあったりするくらい重要なところです。
まずは、基礎を勉強してください。

他にも。

御自身で書いているように, $queryには「●_text=X」が入るわけですよね?
とすると
> if($_ =~ /$query/){
これは
if($_ =~ /●_text=X/){
になる、ということはお理解りですか?
つまり、●_text=Xを検索するもので●_textだけを検索するものではないです
そも、出力例には●_textなんて行はまったくありません。

> #ファイルを削除する
> unlink($open_file_name);
今のままでは +<keep.txt というファイルを消そうとします。
keep.txtではありません。

前回も言いましたけど、最近のPerlならopenは3引数版が推奨ですし、
同じファイル名を使いまわすなら、せめて
$file_name = 'keep.txt'
open A , '+<' , $file_name ;
unlink( $file_name ) ;
open A , '>>' , $file_name ;
とファイル名とオープンモードは別にした方が間違いは少ないです(事実、一緒にして間違えているわけだし)

それから、これも前回言いましたが、CGIでは重要となる「同時にアクセスがあったとき」の対策がまったくありません。
xさんがapple.htmlからa_textを送信したあと、y さんが apple.htmからa_textを送信したら
そのあと xさんがbigin.htmlから送信したときの keep.txtのa=はyさんが入力したものになっています。
二人がほぼ同時に送信した場合は、もっと複雑で中身がちゃんとしているかどうかも保証できません。
それでいいのですね?
    • good
    • 0

おそらく, while 文が全体として間違っている. 特に


@keep = $_;
@keep = $query
のあたりを見ると「そもそも Perl を理解できていない」としか思えない.
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!