• ベストアンサー

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======================= 名前 名字 メールアドレス (実際はきちんとしたものを打ち込みます)

質問者が選んだベストアンサー

  • ベストアンサー
  • misoka
  • ベストアンサー率35% (56/160)
回答No.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; }

masa0720
質問者

お礼

どうもありがとうございました。 あのあと、配列を使う方法を思いつきまして、そちらを実行したらうまくいきました。 #!/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; お手数をおかけしました。

その他の回答 (4)

  • natural
  • ベストアンサー率37% (419/1115)
回答No.4

すみません、外側のwhileを見落としていました。^^; 既に他の方々からより適切な回答が付いているようですので、No.1の回答は無視なさって下さい。 失礼しました。<(_ _)>

  • duckling
  • ベストアンサー率47% (88/185)
回答No.3

================プログラム本体===================== #!/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; こういうことでしょうか?

noname#227796
noname#227796
回答No.2

今、 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)
回答No.1

open TEXT,"text.txt"; この一文をwhileの前に移動すれば良いと思うのですが…。 外していた場合はご容赦を。(^_^;

関連するQ&A

専門家に質問してみよう