我要做的是让我的程序通过一个目录递归,并为目录中的所有文件搜索,搜索每个文件中的单词“ERROR”,然后在一个单独的文件中打印出它的实例。我能够在不进行递归的情况下执行此操作,即只需输入要在cmd中手动检查的文件。我想知道在递归时使用ARGV的正确方法是什么。这是我到目前为止的代码:
#!/usr/bin/perl
use strict;
use warnings;
use File::Find;
my $dir = "c:/programs";
find(\&searchForErrors, $dir);
sub searchForErrors()
{
my $seen = 0;
if (-f){
my $file = $_;
my @errors = ();
open FILE, $file;
my @lines = <FILE>;
close FILE;
for my $line (@lines){
if (/ERROR/ ){
push(@errors, "ERROR in line $.\n");
print FILE "ERROR in line $.:$1\n" if (/Error\s+(.+)/);
}
open FILE, ">$file";
print FILE @lines;
close FILE;
}
}
}
我需要知道的是如何合并ARGV以便程序将读入目录中的每个文件,执行搜索,然后将搜索结果输出到文件。我希望我已经充分解释了我的问题,如果你需要任何澄清,请告诉我什么是令人困惑的。你可以用答案给出的解释越多越好。谢谢!
答案 0 :(得分:4)
ARGV
通常用于迭代从Perl外部提供的文件。
$ find -type f --exec perl script.pl {} +
# script.pl
while (<>) {
print "$ARGV:$.: $1\n" if /Error\s+(.+)/;
} continue {
close(ARGV) if eof; # Reset $.
}
但这没有必要。你也可以这样做:
use File::Find::Rule qw( );
@ARGV = File::Find::Rule->file->in('.');
while (<>) {
print "$ARGV:$.: $1\n" if /Error\s+(.+)/;
} continue {
close(ARGV) if eof; # Reset $.
}
我更喜欢File::Find::Rule,但如果您将上述代码段与以下代码段进行比较,您可以坚持使用File::Find,原因应该很明显:
use File::Find qw( find );
@ARGV = ();
find({ wanted => sub { push @ARGV, $_ if -f }, no_chdir => 1 }, '.');
while (<>) {
print "$ARGV:$.: $1\n" if /Error\s+(.+)/;
} continue {
close(ARGV) if eof; # Reset $.
}
PS - 您正在用自己的精确副本替换每个文件,并且您正在填充一个您从未使用过的数组。我从我的版本中省略了该代码。