Perl:从数组中打开文件并逐个读取

时间:2015-03-14 00:48:10

标签: arrays regex perl

我在Perl中有一个如下所示的数组:

 my @dynfiles = ('dyn.abc.transcript', 'dyn.def.transcript', 'dyn.ghi.transcript', 'dyn.jkl.transcript');

我试图打开这些文件并逐个阅读。为此我有一个代码如下:

foreach my $dynfile (@dynfiles) {
    print "$dynfile\n";
    open my $fh , '<', $dynfile or die "Could not open file\n";
    my %data;
    $data{$dynfile} = do {
        local $/ = undef;
        while (my $line = <$fh>) {
            chomp $line;
            if ($line =~ m/Errors:\s+0/) {
                print "Dyn run status: PASS\n";
            } else { 
                print "Dyn Run status : FAIL\n";
            }
        }
        close $fh;
    }
}

我将此错误视为输出:

dyn.bxt.transcript
Dyn run status: FAIL
dyn.cnl.transcript
17:25:19 : -E- Could not open dyn.cnl.transcript

所以我担心的是它根本不读取数组中的文件。此外,此文件dyn.bxt.transcript中包含此字符串Errors : 0,但我仍然在输出中获得Dyn run status: FAIL。 我在这里做错了吗?我使用简单的模式匹配,不确定问题出在哪里。亲切帮助。

提前致谢!

3 个答案:

答案 0 :(得分:2)

首先,让Perl告诉你它为什么无法打开文件:

open my $fh , '<', $dynfile or die "Could not open file $!\n";

我注意到您的错误消息引用了@dynfiles中不存在的 dyn.bxt.transcript dyn.cnl.transcript 。它有助于您使用示例输入构建完整且最小的脚本。

然后您将取消定义输入记录分隔符,之后使用while,它应该只返回整个文件的单行。这通常是一件坏事。

接下来,如果您的模式看起来不匹配其中有空格的字符串Errors : 0

        if ($line =~ m/Errors\s*:\s+0/) {

我不确定你对do做了些什么。返回最后一个已计算的表达式,在您的情况下为close $fh。但是,%data哈希在块的每次迭代结束时消失。再次,删除不是调查此问题的所有内容。

答案 1 :(得分:2)

在查看您的代码并在聊天中调试之后,我可能会选择以下内容:

sub dynamo_check {

    opendir(my $dh, $log_file) or die "can't opendir $log_file: $!";
    my @dynfiles = grep { /^dynamo.*transcript$/ && -f "$log_file/$_" } readdir($dh);
    close $dh;

    foreach my $dynamofile (@dynfiles) {
        print "Checking file: $dynamofile\n";

        open my $fh, '<', $log_file . $dynamofile or die "$!\n";

        my $passed = 0;

        while(my $line = <$fh>) {
            if ($line =~ m/Errors\s*:\s*0/i) {
                $passed = 1;
                last;
            }
        }
        if ( $passed == 1 ) {
            print "Dynamo run status: PASS\n";
            $data{$dynamofile} = "pass";
        }else {
            print "Dynamo run status: FAIL\n";
            $data{$dynamofile} = "fail";
        }
    }
    print Dumper(\%data);
}

变更摘要:

  • 添加$!以获得更好的错误消息,作为perlvar
  • 中的参考
  • 使用grepreaddir查找您要阅读的文件,而不是硬编码。
  • 在我们打开文件时,将目录路径添加到文件名。
  • 删除do块;
  • %data中的值设置为passfail
  • 此处无需使用chomp
  • 无需设置local $/ = undef;,当我们找到while行时,我们可逐个查看这些行,并使用last跳出Errors循环。

答案 2 :(得分:1)

您可以使用一些经过良好测试的模块来减少代码。例如,使用我最喜欢的Path::Tiny之一,你可以写:

use 5.014;
use warnings;
use Path::Tiny;

my @dynfiles = map { "dyn.$_.transcript" } qw(abc def ghi jkl);
say "Dyn run status: ",
    (path($_)->slurp =~ /error\s*:\s*0\b/i)
        ? "PASS"
        : "FAIL"
    for (grep {-f} @dynfiles);