调整@ARGV 的最大问题是它是一个全局变量。另外,你应该知道它while (<>)
具有特殊的魔法属性。(读取每个文件@ARGV
或处理STDIN
是否@ARGV
为空,测试定义性而不是真实性)。为了减少需要理解的魔法,我会避免它,除了快速黑客工作。
您可以通过检查来获取当前文件的文件名$ARGV
。
您可能没有意识到,但实际上您正在影响两个全局变量,而不仅仅是@ARGV
. 你也打$_
。本地化也是一个非常非常好的主意$_
。
local
您可以通过使用本地化更改 来减少修改全局变量的影响。
顺便说一句,还有另一个重要的、微妙的魔法<>
。假设您要返回文件中匹配项的行号。你可能会想,好吧,检查 perlvar 并 find$.
给出最后访问的句柄中的行号——太棒了。但是这里潜伏一个问题——文件$.
之间没有重置。@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";
}