Reputation: 95
I have an array in Perl that looks like this:
my @dynfiles = ('dyn.abc.transcript', 'dyn.def.transcript', 'dyn.ghi.transcript', 'dyn.jkl.transcript');
I'm trying to open these files and read them one by one. For this I have a code that looks like this:
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;
}
}
And I get this error as output:
dyn.bxt.transcript
Dyn run status: FAIL
dyn.cnl.transcript
17:25:19 : -E- Could not open dyn.cnl.transcript
So my concern is that it isn't reading the files in the array at all. Also, this file dyn.bxt.transcript
had this string Errors : 0
in it, but I still get Dyn run status: FAIL
in the output.
Am I doing anything wrong here? I'm using a simple pattern match, not sure where the problem is..Kindly help.
Thanks in advance!
Upvotes: 3
Views: 251
Reputation: 5139
After viewing reading your code and debugging in chat, I would probably go with something like this:
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);
}
Summary of changes:
$!
to get a better error message as reference in perlvardo
block;%data
to pass
or fail
.local $/ = undef;
, we can go through the lines one by one and break out of the while
loop with last when we find the Errors
line.Upvotes: 2
Reputation: 63902
You can reduce the code using some well tested modules. For example using one of my favourite Path::Tiny, you could write:
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);
Upvotes: 1
Reputation: 132792
First, let Perl tell you why it couldn't open a file:
open my $fh , '<', $dynfile or die "Could not open file $!\n";
I notice that your error message references dyn.bxt.transcript and dyn.cnl.transcript that are not in your @dynfiles
. It helps is you build a complete and minimal script with sample inputs.
Then you are undefining the input record separator, after which you use a while
which should only ever return the single line of the entire file. That's typically a bad thing.
Next, if looks as if your pattern doesn't match the string Errors : 0
that has a space in it.
if ($line =~ m/Errors\s*:\s+0/) {
I'm not sure what you're doing with the do
. That returns the last evaluated expression, which in your case is close $fh
. But, that %data
hash disappears at the end of each iteration of the block. Again, strip out everything that isn't part of investigating this problem.
Upvotes: 2