2012-06-11 31 views
2

我想要做的是让我的程序通过一个目录进行递归,并对目录中的所有文件进行递归,在每个文件中搜索单词“ERROR”,然后打印实例它在一个单独的文件中。我能够做到这一点,而不会使其递归,即只需输入要在cmd中手动检查的文件即可。我想知道递归时使用ARGV的正确方法是什么。这里是我的代码至今:在Perl中通过目录递归时使用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

您用输出覆盖输入文件。这似乎是一个非常糟糕的主意,因为它会截断它找到的每个文件。 – TLP

+0

此外,这是你自己的一个问题的副本:http://stackoverflow.com/q/10918750/725418 – TLP

回答

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 - 你”用自己的确切副本替换每个文件,然后填充一个永远不会使用的数组。我从我的版本中省略了代码。

+0

它不让我使用File :: Find :: Rule,它说它无法定位它在@INC中。有什么我需要下载/添加到我的Perl为此工作? – user1440061

+0

你有它安装?如果你愿意,可以随意使用File :: Find。 File :: Find :: Rule更简单。 – ikegami

+0

我在cmd中做了一些检查,我没有Find :: File :: Rule,现在无法下载它。我是否会在代码中将Find :: File for Find :: File :: Rule替换掉,还是会进行其他更改?我是新来的,所以请耐心等待我 – user1440061