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

I'm reading a file and then running a for loop for each value. My script is stopping after executing the first value. The file_detail.txt has multiple lines. But it is not proceeding to the next value. My script looks something like this --
open (my $fh, "<", "$mycrdir/file_detail.txt" ); foreach(my $value = <$fh>) { chomp($value); if($value eq "abc") { qx/"mkdir $mydir"/; func1($mycrnum,$mydir,$value,%envparams); func2($mycrnum,$mydir,$value,%envparams); } elsif($value eq "123") { qx/"mkdir $mydir"/; func1($mycrnum,$mydir,$value,%envparams); func2($mycrnum,$mydir,$value,%envparams); } }

Replies are listed 'Best First'.
Re: For loop not executing all the values
by Athanasius (Archbishop) on Sep 01, 2015 at 06:46 UTC
Re: For loop not executing all the values
by GrandFather (Saint) on Sep 01, 2015 at 06:54 UTC

    Perl's for loop loops over a list. You have a single item in the list - the first line in the file. Instead you need a while loop which loops while a condition is true. Actually, you need just a little more work than that. You should loop until the file read returns undef. Consider:

    #!/usr/bin/perl use strict; use warnings; my $fileName = "file_detail.txt"; open my $fOut, '>', $fileName or die "Can't create '$fileName': $!\n"; print $fOut <<CONTENT; 123 abc 12ab3c CONTENT close $fOut; open (my $fh, "<", $fileName); while (defined (my $value = <$fh>)) { chomp ($value); if ($value eq "abc") { print "matched 'abc'\n"; } elsif ($value eq "123") { print "matched '123'\n"; } }

    Prints:

    matched '123' matched 'abc'
    Premature optimization is the root of all job security

      Hello GrandFather,

      Instead you need a while loop which loops while a condition is true. Actually, you need just a little more work than that. You should loop until the file read returns undef.

      Well, according to perlsyn#Compound-Statements, “The while statement executes the block as long as the expression is true.” So far, so good. But if that were the whole story, this:

      #! perl use strict; use warnings; print "Contents of \$/: |$/|\n"; print ">$_<\n" while <DATA>; __DATA__ 7 42 0

      would print only the first two lines, since the final line — which is not terminated by a newline — is '0' and therefore false. But the final line is printed, because with the <> operator (or its equivalent readline call) the while condition is tested for definedness, not truth. This is documented in perlop#IO/Operators:

      In these loop constructs, the assigned value ... is then tested to see whether it is defined. The defined test avoids problems where the line has a string value that would be treated as false by Perl; for example a "" or a "0" with no trailing newline.

      All of which is (apparently) undercut by the op’s assertion, below, that adding an explicit test for definedness solved his problem. I don’t know how to explain that. An early version of Perl? A strange value for $/? I do know that perlop#IO/Operators says the following are equivalent:

      while (defined($_ = <STDIN>)) { print; } while ($_ = <STDIN>) { print; } while (<STDIN>) { print; }

      and immediately goes on to imply that explicit assignment to a lexical variable “behaves similarly” to implicit assignment to the default variable, $_.

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

        Hmm, that looks like cargo culting on my part. I had the impression that in the past the explicit assignment broke the special handling for <> in while loop expressions. A quick look through the Perl documentation doesn't support that impression for any version of Perl I've ever used so there is a bunch of code I can tidy up!

        I'll leave my post above as is to avoid confusion for future readers.

        Premature optimization is the root of all job security
      Thanks for the help. Using while loop with defined helped. I tried while, but it was also exiting after the first execution. After putting defined, it is working.
Re: For loop not executing all the values
by dsheroh (Monsignor) on Sep 01, 2015 at 07:02 UTC