2

私がやろうとしているのは、プログラムにディレクトリを介して再帰させ、ディレクトリ内のすべてのファイルについて、各ファイルで「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を組み込む方法です。私の質問を適切に説明したことを願っています。何か説明が必要な場合は、何が混乱しているのか教えてください。あなたが答えで与えることができるより多くの説明は、より良いです。ありがとうございました!

4

1 に答える 1

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 - 各ファイルをそれ自体の正確なコピーに置き換えており、決して使用しない配列を作成しています。私のバージョンからそのコードを省略しました。

于 2012-06-11T16:39:47.280 に答える