2012-06-11 33 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