born_Today has asked for the wisdom of the Perl Monks concerning the following question:

Monks help needed

i am new to perl..i got a output file which contains two different strings. if my search matches string1, just print that line and if my search matches string2 , count the occurances and print the count

i tried the below but it is not printing count

#!/usr/bin/perl my %count; @files = <C:/temp/CHOP/*JUNE*>; foreach $file (@files) { open (FILE,"$file"); print "=====$file=====\n"; while($line= <FILE>) { print "$line" if $line =~ /Total/; } while ($failed= <FILE> ) { if (failed =~ /failed/) { $count{$failed)++; } } close FILE; print "Total Volume Failed to Resolve:$count{$failed} \n" ; }

Replies are listed 'Best First'.
Re: Process multiple files in a directory
by Athanasius (Archbishop) on Jun 27, 2015 at 16:26 UTC

    Hello born_Today, and welcome to the Monastery!

    First, you should always begin your scripts with:

    use strict; use warnings;

    and declare variables with my. You should also test every open and close statement for success, either explicitly, or by adding:

    use autodie;

    to the head of your script.

    Now, your second while loop does nothing, because at the end of the first loop the filehandle FILE is pointing to the end of the file. You could seek to the beginning, but actually there is no need for the second loop — just include the logic for string2 in the first loop. Like this (untested):

    use strict; use warnings; use autodie; my @files = <C:/temp/CHOP/*JUNE*>; for my $file (@files) { my $count = 0; open(my $fh, '<', $file); print "=====$file=====\n"; while (my $line = <$fh>) { if ($line =~ /Total/) { print $line; } elsif ($line =~ /failed/) { ++$count; } } close $fh; print "Total Volume Failed to Resolve: $count\n" ; }

    Note that I have converted FILE into the lexical variable $fh, and used the 3-argument form of open. I have also replaced the %count hash with a simple scalar, which seems to be all that is needed.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Process multiple files in a directory
by aaron_baugher (Curate) on Jun 27, 2015 at 17:51 UTC

    Others have already pointed out your mistakes and provided basic working versions, so here's one using a couple of newer features (for/when and say) to get rid of some of the cruft, which you may be interested in as you learn:

    #!/usr/bin/env perl use 5.010; use strict; use warnings; for my $file (<*>){ # get all filenames in current director +y say "===== $file ====="; open my $fd, '<', $file or die $!; my $count = 0; # counter for /failed/ matches while(my $line = <$fd>){ for($line){ print when /Total/; # print matching lines $count++ when /failed/; # count matching lines } } say "Total Volume Failed to Resolve: $count"; close $fd; }

    Aaron B.
    Available for small or large Perl jobs and *nix system administration; see my home node.

      G'day Aaron,

      I wouldn't recommend showing someone, who's "new to perl", experimental features (without clearly pointing out that they are experimental and why you are using them). I'm not sure what born_Today will make of the follow two lines on stderr:

      when is experimental at <script_name> line 10. when is experimental at <script_name> line 11.

      This code seems overly complicated:

      while(my $line = <$fd>){ for($line){ print when /Total/; # print matching lines $count++ when /failed/; # count matching lines } }

      This may have been better:

      while (<$fd>) { print if /Total/; # print matching lines $count++ if /failed/; # count matching lines }

      -- Ken

        You're right, I got it stuck in my head that I was going to demonstrate for/when, but didn't actually need it at all. I knew something wasn't right there but couldn't put my finger on it. Thanks for pointing it out, and you're right that I should have said it's experimental and limited to newer versions.

        Aaron B.
        Available for small or large Perl jobs and *nix system administration; see my home node.

Re: Process multiple files in a directory
by stevieb (Canon) on Jun 27, 2015 at 16:56 UTC

    Welcome to PerlMonks!

    You should always use strict; and use warnings; at the top of every Perl script. It pinpoints the vast majority of things that are wrong (or could be better) up front, so it forces you to write more predictable, stable code.

    Here's an example of what I think you want to do, using strict, warnings and common Perl idioms. It seems you only want to have a total count, so I got rid of the hash as it isn't needed.

    #!/usr/bin/perl use warnings; use strict; my @files = <C:/temp/CHOP/*JUNE*>; for my $file (@files){ open my $fh, '<', $file or die "Can't open file $file: $!"; my $count = 0; while (my $line = <$fh>){ print "$line" if $line =~ /Total/; $count++ if $line =~ /failed/; } if ($count){ print "Total Volume Failed to Resolve in $file: $count\n"; } }

    Notice that if 'Total' and 'failed' are on the same line, it counts as a 'Total' due to the first if statement. If you want it to fail even though the line contains 'Total':

    if ($line =~ /Total/ and $line != /failed/){ print "$line\n"; }

    -stevieb