人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

CGIの質問です。以下は携帯用メール送信フォームCGI(http://www.deaikensaku.net/o1.shtml)の一部です。
フォームに入力された内容をCSVに書き込みます。次の2つの条件によってCSVに書き込む内容を分岐するにはどこを修正すればよいでしょうか?お智恵をお借りできれば幸いです。
1.メルマガ($newsletter)の値が"希望する"または"登録済み"の場合で
2.docomo,ezweb,softbank,vodafoneを含む携帯アドレスならmail_keitai.csvにそれ以外はmail.csvに書き込む
※これはhttp://q.hatena.ne.jp/1203118562#a802935の派生質問です。アドレスがすでにCSVに存在する場合は2つの条件が当てはまっても書き込みません。

$csv = "1";
$file = "./mail.csv";
$file2 = "./mail_keitai.csv";
$lock = "./lock/mail.dat";
$mail = $FORM{'mail'};
$name = $FORM{'name'};
$newsletter = $FORM{'newsletter'};
$mail2 = $FORM{'mail2'};

#書きこむ
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,"$name,$mail\n");
open(OUT, "+<$file") or &err2();
print OUT @lines;
close(OUT);
}



●質問者: icta
●カテゴリ:ウェブ制作
✍キーワード:CGI CSV dat DoCoMo EZweb
○ 状態 :終了
└ 回答数 : 2/2件

▽最新の回答へ

1 ● tezcello
●35ポイント

最近 perl を書いていないのでチョッと不安がありますが、こんな感じでしょうか。

1)

# 書きこむ

の行の前で、$newsletter の値が"希望する"または"登録済み"でない場合は、このルーチンから抜ければOKでは?

if ($newsletter eq '希望する' || $newsletter eq '登録済み') exit; # または return;


2)

こちらも

# 書きこむ

の行の前でキーワードを含めば、携帯用に書き換えるとよいと思います。

$file = './mail.csv';

if ($mail =~ /(docomo|ezweb|softbank|vodafone)/) $file = $file2; # 前以て$file2を定義せずにここで直接書いても可

◎質問者からの返答

回答ありがとうございます。

1)はこういうことでしょうか?

エラーと表示されるので、恐らく書き方が間違っているのだと思われます。

勉強不足でPerlがよくわからないため、間違いがありましたらご指摘いただければ幸いです。

if ($newsletter eq '希望する' || $newsletter eq '登録済み'){

#書きこむ

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

@lines= <FILE>;

close(FILE);

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

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

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

}

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

unshift(@lines,"$name,$mail,$birthmonth,$birthday\,\n");

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

print OUT @lines;

close(OUT);

}

exit;

}


2 ● kiryuu
●400ポイント ベストアンサー

まず条件を整理します。

1)$newsletterが「希望する」又は「登録する」の場合は書き込み処理を行う。

2)$mailにdocomo,ezweb,softbank,vodafoneのいずれかが含まれれば$file2に書き込み、当てはまらなければ$fileに書き込む。

1の条件式は、($newsletter eq '希望する' || $newsletter eq '登録する') となります。

2で真を返す正規表現は、($mail =~ /(docomo|ezweb|softbank|vodafone)/) となります。

他の方は$fileを上書きする方法を採られていますが、私は専用の変数(この場合$wfile)を使用する方が好きです。(単に好みの問題です)

$csv = "1";
$file = "./mail.csv";
$file2 = "./mail_keitai.csv";
$lock = "./lock/mail.dat";
$mail = $FORM{'mail'};
$name = $FORM{'name'};
$newsletter = $FORM{'newsletter'};
$mail2 = $FORM{'mail2'};

#書きこむ
#newsletterの値が'希望する'か'登録する'ならば実行する。
#それ以外なら何もしない

if($newsletter eq '希望する' || $newsletter eq '登録する'){

#メールアドレス内文字列の判定を行う
my $wfile;# $wfileを局所化します。他で使っていなければやらなくてもOK
if($mail =~ /(docomo|ezweb|softbank|vodafone)/){
$wfile = $file2;
}else{
$wfile = $file;
}

open(FILE, "<$wfile") 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,"$name,$mail\n");
open(OUT, "+<$wfile") or &err2();
print OUT @lines;
close(OUT);
}

}

ただ、質問文を読んでみると携帯電話用のアドレスとそれ以外のアドレスを別々のファイルで管理したいかの様に思えます。

($mail =~ /(docomo|ezweb|softbank|vodafone)/) ですと、例えば「docomonsense@hatena.ne.jp」(DoCommonSenseのミススペル)も「携帯電話アドレス」と判定されます。

Docomoのメールアドレスは、?@docomo.ne.jp

ezwebのメールアドレスは、?@ezweb.ne.jp

SoftBankのメールアドレスは、?@softbank.ne.jp

Vodafoneのメールアドレスは、?@*.vodafone.ne.jp

ですので、

($mail =~ /(\@docomo\.ne\.jp|\@ezweb\.ne\.jp|\@softbank\.ne\.jp|\.vodafone\.ne\.jp)/)

が適切かと。

更に、これらのドメインは末尾にくるはずなので、

($mail =~ /(\@docomo\.ne\.jp|\@ezweb\.ne\.jp|\@softbank\.ne\.jp|\.vodafone\.ne\.jp)$/)

この場合の//内の「$」は、文字列の末尾を表します。

ついでに、ドメインネームについては大文字小文字を区別しませんので、

($mail =~ /(\@docomo\.ne\.jp|\@ezweb\.ne\.jp|\@softbank\.ne\.jp|\.vodafone\.ne\.jp)$/i)

//の外の「i」は、大文字小文字を区別しないパターンマッチを行う修飾子です。


これをメールアドレス内文字列の判定に適用すると、

#メールアドレス内文字列の判定を行う
my $wfile;# $wfileを局所化します。他で使っていなければやらなくてもOK
if($mail =~ /(\@docomo\.ne\.jp|\@ezweb\.ne\.jp|\@softbank\.ne\.jp|\.vodafone\.ne\.jp)$/i){
$wfile = $file2;
}else{
$wfile = $file;
}

こんな感じになるかと思います。

また、[例えば]ezwebが?@*.ezweb.ne.jp というメールアドレスも使い始めたら、「\@ezweb\.ne\.jp」の後にでも「|\.ezweb\.ne\.jp」を書き加えます。「\.ezweb\.ne\.jp」は、()外の$と合わさり「末尾が.ezweb.ne.jpで終わる」文字列にマッチします。

ウィルコムも仲間に加える場合は、

($mail =~ /(\@docomo\.ne\.jp|\@ezweb\.ne\.jp|\@softbank\.ne\.jp|\.vodafone\.ne\.jp|\.pdx\.ne\.jp|\@pdx\.ne\.jp)$/i)

です。

◎質問者からの返答

こんにちは、kiryuuさん

詳細に回答していただき本当にありがとうございました。

私はCGIとPerlの違いもよくわかっていない程の知識しか持ち合わせていないので丁寧に回答していただいて本当に助かりました。

時間がかかりましたが、ようやく教えていただいた内容をCGIに組み込むことに成功しました。

最後にもう1点だけ教えていただけませんでしょうか?

この実際に運用しているフォームの中には誕生月($birthmonth)と誕生日($birthday)を聞く欄があります。

誕生月と誕生日を教えたくない人もいますのでその場合はハイフン(-)を選択してもらいます。

ハイフンを選択した場合はCSVファイルに何も書き込まないようにために以下のように考えたのですが書き込まれてしまいます。

何か根本的なところを間違っているのでしょうか?

別の質問になるため本来は新たな質問を起こさなければならないは思うのですが、質問は800文字の文字制限があって質問の内容が正確に伝わりません。

最後にこの1点だけ教えていただければ幸いです。

if($birthmonth ne '-' || $birthday ne '-'){

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

@lines= <FILE>;

close(FILE);

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

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

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

}

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

unshift(@lines,"$name,$mail,$birthmonth,$birthday\n");

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

print OUT @lines;

close(OUT);

}

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ