- ベストアンサー
Perlプログラムの変更方法
メーリングリストのようなものをPerlで作って いるのですが、text.txtを一回だけ読み込むような プログラムに変更したいのですが、どこをどのように 変更すれば良いのでしょうか。 ================プログラム本体===================== #!/usr/bin/perl $wunderprize='100% genuine faux diamond'; open LIST,"list.txt"; while($name =<LIST>){ chomp($name); @f=split(/\s+/,$name); if($f[2] ne""){ open MAIL, "|mail $f[2]"; open TEXT,"text.txt"; while($line=<TEXT>){ $line=~ s/<FIRST>/$f[0]/g; $line=~ s/<FAMILY>/$f[1]/g; $line=~ s/<SUCKER>/$f[0] $f[1]/g; $line=~ s/<TRINKET>/fabulous $wunderprize/g; print MAIL "$line\n"; } close MAIL; close TEXT; } } close LIST; ==============text.txt======================== Dear <FIRST>, You have been chosen to win a brand new <TRINKET>!Free! Could you use another <TRINKET> in the <FAMILY> household? Yes <SUCKER>, I bet you could! Just respond by... ===============list.txt======================= 名前 名字 メールアドレス (実際はきちんとしたものを打ち込みます)
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
はじめに"text.txt"を読んでしまうのがよいでしょうね。 サブルーチンをつくるとスッキリ分かりよくなります。 例えば↓のような感じなんてどうでしょうか。 (インデントの替わりに全角スペースが入ってます) -- #!/usr/bin/perl # テキストを読む my $text = &readText; # リストを開く open LIST, "list.txt"; while( <LIST> ) { chomp; @f = split( /\s+/ ); if( $f[2] ne "" ) { # メールに書く &printMail( $f[0], $f[1], $f[2], $text ); } } close LIST; exit; # テキストを読む sub readText { my $lines; open TEXT, "text.txt"; while( <TEXT> ) { $lines .= $_; } close TEXT; return( $lines ); } # メールに書く sub printMail { my( $last_name, $first_name, $address, $mail ) = @_; $wunderprize = '100% genuine faux diamond'; $mail =~ s/<FIRST>/$last_name/g; # ... その他置換する open MAIL, "|mail $address"; print MAIL "$mail\n"; close MAIL; }
その他の回答 (4)
- natural
- ベストアンサー率37% (419/1115)
すみません、外側のwhileを見落としていました。^^; 既に他の方々からより適切な回答が付いているようですので、No.1の回答は無視なさって下さい。 失礼しました。<(_ _)>
- duckling
- ベストアンサー率47% (88/185)
================プログラム本体===================== #!/usr/bin/perl $wunderprize='100% genuine faux diamond'; open LIST,"list.txt"; open TEXT,"text.txt"; while($name =<LIST>){ chomp($name); @f=split(/\s+/,$name); if($f[2] ne""){ open MAIL, "|mail $f[2]"; while($line=<TEXT>){ $line=~ s/<FIRST>/$f[0]/g; $line=~ s/<FAMILY>/$f[1]/g; $line=~ s/<SUCKER>/$f[0] $f[1]/g; $line=~ s/<TRINKET>/fabulous $wunderprize/g; print MAIL "$line\n"; } close MAIL; } } close TEXT; close LIST; こういうことでしょうか?
今、 open TEXT,"text.txt"; close TEXT; が、 while($name =<LIST>){ のループ内に入っていますので、 if($f[2] ne""){ にマッチする場合には、必ず呼び出され、何度も実行されてしまいます。 一つの例ですが、先のopen、closeの行は削除し、 while($name =<LIST>){ の前で open(TEXT,"text.txt"); @lines = <TEXT>; close(TEXT); として、配列@linesに各行を突っ込み(巨大なファイルだとメモリ食いますが)、 while($line=<TEXT>){ のところを foreach $line (@lines) { としてみてはいかがでしょう?
- natural
- ベストアンサー率37% (419/1115)
open TEXT,"text.txt"; この一文をwhileの前に移動すれば良いと思うのですが…。 外していた場合はご容赦を。(^_^;
お礼
どうもありがとうございました。 あのあと、配列を使う方法を思いつきまして、そちらを実行したらうまくいきました。 #!/usr/bin/perl $wunderprize='100% genuine faux diamond'; open LIST,"list3.txt"; while($name =<LIST>){ chomp($name); @f=split(/\s+/,$name); open TEXT,"text2.txt"; if($f[2] ne""){ open MAIL, "|mail $f[2]"; # open TEXT,"text2.txt"; @line=<TEXT>; $a=@line; $i=0; while($i<$a){ $line[$i]=~ s/<FIRST>/$f[0]/g; $line[$i]=~ s/<FAMILY>/$f[1]/g; $line[$i]=~ s/<SUCKER>/$f[0] $f[1]/g; $line[$i]=~ s/<TRINKET>/fabulous $wunderprize/g; print MAIL "$line[$i]\n"; print MAIL "$count\n"; $i++; } close MAIL; close TEXT; } } close LIST; お手数をおかけしました。