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

Hi, I do not understand what is happening to $_ (or not) in this while() construct:
my $fname = "while_multi_cond.dat"; my $s1 = ""; open( FP, "<", $fname ) or die "Can't open $fname: $!"; while(<FP>) { if (/^_start/) { # This works as expected # while(<FP> ) { # if (/^_stop/) { last } # I'm trying to replace it with this: while( (<FP>) && (!/^_stop\n/) ) { # but seems to break the functionality of $_ $s1 .= $_; } } if ($_) { print("$_") } } print("\$s1= \n<$s1>");
The data file looks like this:
The file: while_multi_cond.dat ----- no1 no2 _start yes 1 yes 2 _stop no3 no4 ----------
In the program output below you can see how $_ retains the value obtained in the outer loop:
~> ./while_multi_cond.pl parse_data> ./while_multi_cond.pl no1 no2 _start $s1= <_start _start _start _start _start _start >
Why doesn't $_ contain the new lines as they are read in? Thanks, Howard

Replies are listed 'Best First'.
Re: using multiple conditionals in a while(test)
by BrowserUk (Patriarch) on Dec 04, 2010 at 06:57 UTC

    In a limited set of cases, Perl applies special treatment to while loops. One such case is when the condition is a read from a file.

    In these special cases while( COND ) { gets translated into while( defined( local $_ = COND ) ) {.

    But for this to happen, COND has to be a 'simple' condition.

    Your example:

    while( (<FP>) && (!/^_stop\n/) ) {

    doesn't satisfy this requirement.

    To compensate, you would have to explicitly code that to use $_. Ie.

    while( defined( local $_ = <FP> ) and ! /^_stop\n/ ) {

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      gets translated into while( defined( local $_ = COND ) ) {.

      Not quite.    The $_ variable is NOT localized in a while loop:

      $ echo "one two three four five six seven eight nine ten" | perl -e' while ( <> ) { last if /seven/; } print "$.: $_\n"; ' 7: seven

        You're right.

        C:\test>perl -MO=Deparse -e"while( <> ) { print }" while (defined($_ = <ARGV>)) { print $_; } -e syntax OK

        But if you're doing it yourself, it's as well to.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.