【问题标题】:Using ARGV When Recursing through Directories in Perl在 Perl 中通过目录递归时使用 ARGV
【发布时间】:2012-06-12 03:30:48
【问题描述】:

我想要做的是让我的程序通过一个目录递归,并且对于目录中的所有这些文件,在每个文件中搜索单词“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,以便程序读取目录中的每个文件,执行搜索,然后将搜索结果输出到文件。我希望我已经充分解释了我的问题,如果您需要任何澄清,请告诉我什么是令人困惑的。您可以对答案给出的解释越多越好。谢谢!

【问题讨论】:

  • 你用输出覆盖你的输入文件。这似乎是一个非常糟糕的主意,因为它会截断找到的每个文件。
  • 另外,这是您自己的问题之一的重复:stackoverflow.com/q/10918750/725418

标签: perl argv


【解决方案1】:

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,如果你将上面的sn-p与下面的sn-p进行比较,原因应该很明显:

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 - 您正在将每个文件替换为其自身的精确副本,并且您正在填充一个您从未使用过的数组。我从我的版本中省略了该代码。

【讨论】:

  • 它不允许我使用 File::Find::Rule,它说它无法在 @INC 中找到它。我需要下载/添加到我的 perl 中才能正常工作吗?
  • 你安装了吗?如果需要,请随意使用 File::Find。使用 File::Find::Rule 更简单。
  • 我在 cmd 中做了一些检查,显然我没有 Find::File::Rule 并且现在无法下载。我是否可以在代码中将 Find::File 替换为 Find::File::Rule,还是需要进行其他更改?我是新手,所以请多多包涵
  • 我正在使用 File::Find::Rule 创建名称列表。你必须使用 File::Find 来做同样的事情。您不能只更改“使用”行。
  • 好吧,我现在迷路了...你能帮我解决一下如何使用 File::Find 而不是 File::Find::Rule 吗?请原谅我的无知
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-01
  • 2011-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多