@ARGVを微調整する際の大きな問題は、それがグローバル変数であるということです。while (<>)
また、には特別な魔法の属性があることに注意する必要があります。(各ファイルを読み込んだり、空の場合は@ARGV
処理したりして、真実ではなく定義をテストします)。理解する必要のある魔法を減らすために、quickie-hack-jobsを除いて、私はそれを避けます。STDIN
@ARGV
をチェックすると、現在のファイルのファイル名を取得できます$ARGV
。
気付いていないかもしれませんが、実際には、だけでなく2つのグローバル変数に影響を与えています@ARGV
。あなたも打って$_
います。ローカライズすることも非常に良い考え$_
です。
local
を使用して変更をローカライズする ことにより、グローバル変数の変更による影響を減らすことができます。
ところで、。にはもう1つの重要で微妙な魔法があり<>
ます。一致する行番号をファイルに返したいとします。perlvarをチェック$.
して、最後にアクセスしたハンドルの行番号が表示されると思うかもしれません。しかし、ここに潜んでいる問題があります-ファイル$.
間でリセットされません。@ARGV
これは、処理した合計行数を知りたい場合に最適ですが、現在のファイルの行番号が必要な場合は役立ちません。eof
幸いなことに、この問題を解決する 簡単なトリックがあります。
use strict;
use warnings;
...
searchDir( 'foo' );
sub searchDir {
my $dirN = shift;
my $pattern = shift;
local $_;
my @fileList = grep { -f $_ } glob("$dirN/*");
return unless @fileList; # Don't want to process STDIN.
local @ARGV;
@ARGV = @fileList;
while(<>) {
my $found = 0;
## Search for pattern
if ( $found ) {
print "Match at $. in $ARGV\n";
}
}
continue {
# reset line numbering after each file.
close ARGV if eof; # don't use eof().
}
}
警告:ブラウザでコードを変更しました。私はそれを実行していないので、タイプミスがある可能性があり、少し調整しないと機能しない可能性があります
更新:local
代わりに使用する理由my
は、それらが非常に異なることを行うためです。 含まれているブロックにのみ表示され、シンボルテーブルからアクセスできない my
新しい字句変数を作成します。既存のパッケージ変数local
を保存し、それを新しい変数にエイリアスします。新しいローカライズされたバージョンは、囲んでいるブロックを離れるまで、後続のコードに表示されます。perlsub:local()による一時的な値を参照してください。
新しい変数を作成して使用する一般的なケースでmy
は、が正しい選択です。 local
グローバルを使用している場合は適切ですが、変更をプログラムの残りの部分に伝播しないようにする必要があります。
この短いスクリプトは、ローカルを示しています。
$foo = 'foo';
print_foo();
print_bar();
print_foo();
sub print_bar {
local $foo;
$foo = 'bar';
print_foo();
}
sub print_foo {
print "Foo: $foo\n";
}