0

1つの引数を取り、結果を配列に格納した後、配列内の要素に移動し、配列の要素を引数として自分自身を呼び出し、新しい結果を配列にプッシュするperlスクリプトがあります。何らかの理由で動作させることができず、配列が変更されません。

私は次のようなものを持っています:

#some code here that stores result in @result
foreach $i (@result){
    push(@result, `perl ./myperlscript.pl "$i"`);
}

これを機能させるにはどうすればよいですか?これよりも良い myperlscript.pl を再帰的に呼び出す方法はありますか?

4

2 に答える 2

4

自分自身を呼び出すスクリプトを作成している場合は、設計上の問題が発生する可能性があります。メインロジックをサブルーチンに入れて、それを呼び出してみてください。これにより、シェルからの脱出がないため、より詳細な制御が可能になり、より安全になります。

また、繰り返し処理する配列を変更しないでください。これは良いかもしれません:

my @tmp = ();
foreach my $i (@array) {
    push @tmp, function($i);
}
push @array, @tmp;

いつまでも入りたくない場合は、従来のforループを使用する必要があります。

# infinite loop! Yay!
for (my $i = 0; $i < @array; $i++) {
    push @array, function($i);
}

スクリプトを再構築できず、スクリプト自体を呼び出し続ける必要がある場合は、引数を同じ行に配置するのではなく、パイプでつなぐ必要があります。利点には、データの長さが無限であり、安全性が向上することが含まれます(シェルが逃げることはありません!)。のような不正な形式のデータで何が起こる可能性があるかを考えてみてx" | tee "mySecretFileください。そしてそれは無害です。しかし、繰り返しになりますが、その代わりにサブルーチンを宣言してください。

于 2012-08-20T10:50:28.313 に答える
2

Perl はシェルではありません。一般的には、他に選択肢がない場合や、意図的に手っ取り早いハックを行っている場合を除き、バッククォート演算子と system() 関数を使用しないことをお勧めします。

サブルーチンを書き、そのように再帰を行うことを学びましょう。サブルーチンのこつがなければ、再帰に取り組むべきではありません。


とにかく、あなたがしていることについて話し合いましょう。

バックティックの呼び出しは問題ありません:

`perl ./myperlscript.pl "$i"`

...そして、そのプロセスがstdoutに入れるものは何でも返します。したがって、プログラムは標準出力に出力する必要があります。

Perl では、反復されるリストに項目を追加すると、反復続行されます。

push (@arr,10);
foreach $i (@arr) {
   print "$i\n";
   if($i > 0) {
      push(@arr,$i-1);
   }
}

... 10 から 0 までのカウントダウンを出力します。そのため、コードが機能する可能性があります。しかし、これは紛らわしいモデルであり、慣れるには良い習慣ではないと思います。ループしているデータ構造を変更することは、一般的に良い習慣とは見なされません。

あなたのコードは、停止条件の証拠を示しませんでした。再帰するときは、常に停止条件を考慮する必要があります。

バックティック呼び出しで @result 配列に何が起こっても、現在のプロセスの @result 配列には影響しないことに注意してください。それらは互いに見えません。

于 2012-08-20T11:20:02.900 に答える