CGIの質問です。以下は携帯用メール送信フォームCGI(http://www.deaikensaku.net/o1.shtml)の一部です。

フォームに入力された内容をCSVファイルに書き込みます。
フォーム送信後にCSVファイルからメールアドレスの重複チェックを行い、CSVファイルにすでに同じメールアドレスが存在していれば書き込まない、存在していなければ書き込むようにするにはどこを修正すればよいでしょうか?お智恵をお借りできれば幸いです。

$script = "./i_mail.cgi";
$form = "../i_mail.html";
$list1 = "■お名前";
$list2 = "■内容";
$list3 = "■メールアドレス";
$csv = "1";
$file = "./mail.csv";
$lock = "./lock/mail.dat";

$mail = $FORM{'mail'};
$name = $FORM{'name'};
$goiken = $FORM{'goiken'};
$hensin = $FORM{'hensin'};
$kakunin = $FORM{'kakunin'};
$mail2 = $FORM{'mail2'};

#書きこむ
open(FILE, "<$file") or &err2('エラーです。');
@lines= <FILE>;
close(FILE);

unshift(@lines,"\,$data_now,$name,$mail,$user,$ip,$browser,$goiken\n");
open(OUT, "+<$file") or &err2();
print OUT @lines;
close (OUT);

回答の条件
  • 1人5回まで
  • 登録:2008/02/16 08:36:02
  • 終了:2008/02/16 14:40:37

ベストアンサー

id:kiryuu No.1

kiryuu回答回数16ベストアンサー獲得回数42008/02/16 10:45:49

ポイント400pt

使用目的は問わず、純粋にCGIの質問として回答いたします。

また、使用言語が書かれておりませんが、中身からして多分Perlではないかと推測しますので、Perl5であることを前提とした回答です。

ハッシュを使う方法と、配列を1つ1つチェックしてフラグを立てる方法の2通りを紹介します。

なお、ファイルロックなどは組み込んでいませんので、実際の運用の際には適切に組み込んでください。



ハッシュを使う方法です。

#書きこむ 以下を次のようにしてはいかがでしょう。

  • はじまり---------

#書きこむ

open(FILE, "<$file") or &err2('エラーです。');

@lines= <FILE>;

close(FILE);

#ハッシュにデータを入れる

#使い捨ての配列変数でデータを取り出す

#ついでにメールアドレスをキーにしたハッシュを作成する

for($x=0;$x <= $#lines;$x++){

my @HashTmp = split("\,",$lines[$x]);

$Hname{$HashTmp[2]} = $HashTmp[1]; #代入する値はなんでもよい

}

#ハッシュキー(メアド)が存在するか確認。

#偽ならば書き込み処理・真ならばなにもしない

unless(exists($Hname{$mail})){

unshift(@lines,"$data_now,$name,$mail,$user,$ip,$browser,$goiken\n");

open(OUT, "+<$file") or &err2();

print OUT @lines;

close(OUT);

}

  • おわり---------

unshift内で@linesに追加するデータですが、

“\,”は何か意味がありますか?(先頭を空データにしたいなら“,”でよろしいかと)

今回は、存在を無視しています。(データは$data_nowからはじまります)


解説:

#ハッシュにデータを入れる のfor構文内で、使い捨ての配列変数@HashTmpに@linesのデータを格納します(カンマ区切り)

次の行で、メールアドレスをキーにしたハッシュを作成します。今回は、ハッシュのキーが重要ですので、ハッシュの中身は何でも構いません。

前述の“\,”を残すのなら、ここは

$Hname{$HashTmp[3]} = $HashTmp[1];

としてください。


ハッシュのキーが存在するか確認するにはexists関数を使います。

#ハッシュキー(メアド)が存在するか確認。 以下でハッシュ%Hnameのキーとして$mailが存在するかチェックし、そんざい「していなければ」書き込み処理を行い、存在していれば何もしません。


existsやハッシュについては、

 perldoc http://perldoc.perl.org/functions/exists.html

 SiteCooler http://www.site-cooler.com/kwl/perl/4.htm

などを参照してください。

GoogleやYahoo!JAPANで「perl ハッシュ exists」を検索キーにすればぞろぞろ出てきます。



こちらはハッシュを使わずに一件一件比較して存在したらフラグを立てるという方法です。

  • はじまり---------

#書きこむ

open(FILE, "<$file") or &err2('エラーです。');

@lines= <FILE>;

close(FILE);

#データを解析

#ついでに比較

$mail_flag = 0; #重複チェックフラグ

for($x=0;$x <= $#lines;$x++){

my @HashTmp = split("\,",$lines[$x]);

$mail_flag = 1 if($HashTmp[2] eq $mail);

}

#フラグをチェック

#偽ならば書き込み処理・真ならばなにもしない

unless($mail_flag){

unshift(@lines,"$data_now,$name,$mail,$user,$ip,$browser,$goiken\n");

open(OUT, "+<$file") or &err2();

print OUT @lines;

close(OUT);

}

  • おわり---------


ハッシュの概念を理解できないうちは、1件1件チェックしてフラグを立てる方がわかり易いかと思います。

今回の場合は、データファイルの中身を@linesに格納しているので、どっちにしろループを回さなければならないのでどちらもあまり変わりませんが、今後データをソートしたりすることがあれば、ハッシュを使った方法も知っておくと幸せになれるかもしれません。



別解:

for($x=0;$x <= $#lines;$x++){

my @HashTmp = split("\,",$lines[$x]);


は次のようにも書き換えられます。

foreach(@lines){

my @HashTmp = split("\,",$_);


すっきりしていて個人的には好きですが、$_が何か理解できないうち(昔の私)は、愚直にforで回していった方がわかりやすいかと思います。

id:icta

親切丁寧に教えていただきありがとうございました。

希望通りメールアドレスが重複している場合は書き込まないようにすることができました。

これまで重複チェックにはエクセルで開いてアドレスの重複を調べていたのでこれで作業を軽減することができます。

私の知識が浅いためハッシュについてまだよくわからないのですが勉強してみます。

>使用目的は問わず、純粋にCGIの質問として回答いたします。

このCGIは携帯、PC両方に使えて非常にシンプルに書かれているため純粋にメルマガ登録用のフォームとして重宝しています。

出会い系などには一切使用しておりません。

メルマガ登録フォームとしてはアドレスの重複チェックの他にもう2つ実現したいことがあります。

これも現在エクセルを使って手作業で行っているものです。

1.メルマガ登録の選択で希望する、登録済みを選んだ人はCSVに書き込む。希望しないを選んだ場合は書き込まない。

2.docomo,ezweb,softbank,vodafoneを含む携帯アドレスならmail_keitai.csvにそれ以外はmail.csvに書き込む

これらについては質問の内容が異なるため新しく質問を投稿しました。

もしお力添えをいただければ大変うれしいです。

http://q.hatena.ne.jp/1203138749


>“\,”は何か意味がありますか?(先頭を空データにしたいなら“,”でよろしいかと)

特に意味はありません。質問に記載したURLからダウンロードしたファイルの中ですでにこのようになっておりました。


これで長年の煩わしい作業がから解放されると思うとうれしくて仕方ありません。

本当にありがとうございました。

2008/02/16 14:36:26

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません