2016-03-19 4 views
2

私は変数の宣言を考慮してこの問題を回避するのが難しいです。シナリオ:私は10語のファイルを1行に1つずつ持っています。まず、ファイルをループして、そのデータに基づいて新しいファイルを作成します。例Perlのforeachループでファイルを開いたり閉じたりするために同じ変数を使用する

banana 
apple 
coconut 
strawberry 

--> 

banana.txt 
apple.txt 
coconut.txt 
strawberry.txt 

私がいる最初の問題は、次のとおりです。は、どのように私は、ループ内の各ファイルのファイルハンドルのためのユニークな変数を割り当てるのですか?私はこのような何かを書くだろうが、それが進むべき道だ場合、私は知らない。

open(my $tokensfh, '<', $tokensfile) 
    or die "cannot open file $tokensfile"; 
chomp(my @tokenslines = <$tokensfh>); 
close $tokensfh; 

foreach my $token(@tokenslines) { 
    open(my $token.'fh', '>>', $token."data.txt"); 
} 

ビットさらに私は$トークンに対して、他のデータと一致しますが、私が対処する方法がわからないよラインの下変数:

foreach my $somedata(@data) { 
    my $datatoken = $somedata=~ /<fruit>(.+)<\/fruit>/; 

    # Do I need a new variable name here? 
    foreach my $tokensline(@tokenslines) { 
     if ($datalinetoken eq $datatoken) { 
      # print $somedata to specific file 
      print $tokensline.'fh' "average run time\n"; 
     } 
    } 
} 

新しい変数名が必要ですか?ない場合は、どのように私は、変数割り当ての問題を得ることなく、以前の変数を再利用することができますか?これを行うより良い方法はありますか? (すべての質問にお答えください。)

+0

'my%fh;私の$トークンをforeachする(@tokenslines){ open(my $ fh {$ token}、 '>>'、$ token。 "data.txt")または "恐ろしい死" } '? –

+0

きちんとしたOOフレーバーがケトルに投げ込まれているかもしれません; – laune

+0

ああ、いくつかのサンプルデータは良いでしょう。これはXMLのように見えるので、XMLパーサーが推奨されます。 – Sobrique

答えて

3

あなたは限りが異なるスコープで宣言されていると、繰り返し同じグローバル変数名を使用することができます。 Perlは同じ変数を2回宣言すると警告します。私は同じ名前を使用しました$fhファイルハンドルの下に私のコードでは何も結果なしで

この場合、あなたはそれらの全体のセットが必要なので、ほとんどのプログラムのために開く必要がありますそれはあなただけのそれは次のようになりトークン文字列

でハッシュのインデックスを作成することで、正しいファイルハンドルを選ぶことができるように、ハッシュを使用するのが最も簡単だように見えます。すべてのIO操作の状態を明示的にチェックする必要がないように、私はuse autodieを使用しました。あなたはまた、ああ

(!とものすごくてWindowsを混乱させる)あなたは3つのファイルハンドルを作成します。現時点ではappleAPPLEApple、違いを処理する必要があるかどうかを検討する必要があり、および方法によって、それはですちょうどwhile代わりの配列にそれをすべて読み、そこ

use strict; 
use warnings 'all'; 
use v5.14.1; # For autodie 
use autodie; 

use constant TOKENS_FILE => 'tokens.txt'; 
use constant XML_FILE => 'data.xml'; 

my %token_fh; 

{ 
    open my $fh, '<', TOKENS_FILE; 

    while (<$fh>) { 
     chomp; 
     open $token_fh{$_}, '>', "${_}data.txt"; 
    } 
} 

{ 
    open my $fh, '<', XML_FILE; 

    while (<$fh>) { 

     next unless my ($token) = m|<fruit>(.+)</fruit>|; 
     next unless my $fh = $token_fh{$token}; 

     print $fh "average run time\n"; 
    } 
} 

close $_ for values %token_fh; 



からのデータを処理してラインによって各ファイルの行を処理することがはるかに立派0

別の方法は、それらがXMLに遭遇しているよう完全にトークンファイルを忘れて、ちょうど開いているファイルことであろう。それはこのようになります

use strict; 
use warnings 'all'; 
use v5.14.1; # For autodie 
use autodie; 

use constant XML_FILE => 'data.xml'; 

my %token_fh; 

open my $fh, '<', XML_FILE; 

while (<$fh>) { 

    next unless my ($token) = m|<fruit>(.+)</fruit>|; 

    unless (exists $token_fh{$token}) { 
     open $token_fh{$token}, '>', "${token}data.txt"; 
    } 
    my $fh = $token_fh{$token}; 

    print $fh "average run time\n"; 
} 

close $_ for values %token_fh; 
3

はこれをしないでください。変数名を使用するのは非常に面倒です。理由の詳細については、このリンクを参照してください。http://perl.plover.com/varvarname.html

名前付きファイルハンドルが必要な場合は、ファイルハンドルのハッシュを使用するほうがずっと良いでしょう。ハッシュは、あなたがここで必要とするものであるポータブルネームスペースです。

ので:

my %fh_for; 
foreach my $token (@tokenlines) { 
    open (my $fh_for{$token}, '>', "$token.txt") or die $!; 
} 

foreach my $datalinetoken (@tokenslines) { 
    if ($datalinetoken eq $datatoken) { 
     # print $somedata to specific file 
     print {$fh_for{$datalinetoken}} "average run time\n"; 
    } 
} 

その後は、動的変数の命名の不快messynessを必要とせずに、自分のトークン名をキーファイルハンドルに書き込むことができます。注、私は{}であなたのFHを含めました - それはこれを評価」にPerlを伝える必要があります。

+0

[print](http://perldoc.perl.org/functions/print.html)から、以下のように書かれています:もしあなたが配列やハッシュでハンドルを格納しているのなら、 barewordハンドルや単純なunsubscriptedスカラー変数よりも、ファイルハンドル値を返すブロックを使用する必要があります。その場合、LISTを省略することはできません:_。だから、これはブロックが必須だと私は思う。 –

+0

したがって、$ tokenと$ datatokenは同じものですが、同じ変数名を使用することはできません。 (埋め込みforループを忘れてしまったことに注意してください。) –

+0

うん、良い点。私は確信していませんでした - 私はそれがあった場所をヒットしたことを知っています、私はちょうどこれが1つだったかどうか思い出せません – Sobrique

関連する問題