我有一个简单的任务,即创建一个以文件名作为参数的脚本,读取每个文件中的每一行并检查一些内容。
我试过这样做:
foreach $file (@ARGV){
while (chomp($line = <>)){
...
}
}
虽然我明白虽然只是阅读所有文件,并且这种方法不好,但我注意到在每次“foreach”迭代后,@ ARGV丢失了一个条目,好像有一个
shift @ARGV;
如果没有
,则不会发生这是我不理解的部分,想要解释。为什么@ARGV每次只减少1个元素?
例如,如果我用
调用脚本./test.pl localhost_access_log*.txt
并且有文件
localhost_access_log.2008-02-24.txt
localhost_access_log.2008-02-25.txt
在当前文件夹中,在foreach循环之后,@ ARGV将不会同时拥有它们,而只有一个。
答案 0 :(得分:6)
while (<>) {
... # code for each line
}
等效于以下类似Perl的伪代码:
unshift(@ARGV, '-') unless @ARGV;
while ($ARGV = shift) {
open(ARGV, $ARGV);
while (<ARGV>) {
... # code for each line
}
}
它确实会移动
@ARGV
数组并将当前文件名放入$ARGV
变量中。它还在内部使用文件句柄ARGV
。<>
只是<ARGV>
的同义词,这是神奇的。 (上面的伪代码不起作用,因为它将<ARGV>
视为非魔法。)
答案 1 :(得分:4)
从ARGV
读取已遍历@ARGV
,因此您的代码毫无意义。也许您不知道<>
表示readline(ARGV)
,while (<>)
表示while (defined($_ = readline(ARGV)))
,while ($line = <>)
表示while (defined($line = readline(ARGV)))
。你应该使用
while ($line = <>) {
chomp($line);
...
}
ARGV
会在@ARGV
打开它们时删除。例如,
print "Files to read: @ARGV\n";
while (<>) {
chomp;
print "Read $_ from $ARGV. Files left to read: @ARGV\n";
}
给出
$ script foo bar baz
Files to read: foo bar baz
Read foo1 from foo. Files left to read: bar baz
Read foo2 from foo. Files left to read: bar baz
Read bar1 from bar. Files left to read: baz
Read bar2 from bar. Files left to read: baz
Read baz1 from baz. Files left to read:
Read baz2 from baz. Files left to read: