[comp.lang.perl] Why does my variable keep changing?!!

merlyn@iwarp.intel.com (Randal Schwartz) (11/15/90)

In article <27962@sequoia.execu.com>, painter@sequoia (Tom Painter) writes:
| In the following script, I trying to strip all lines before the first
| blankline from stdin.  In that vein, I set a flag ($header) to "Y"
| and change it to "N" after it hits the blank line.  So far it works.
| However, when I return to the top of the while loop, $header has been changed 
| back to "Y".  The "N" should last for the rest the time, I never want it
| changed back. 
[...]
| #! /usr/bin/perl
| 
| $header = "Y";
| 
| while (<>) {
| print $header;
| 	if ($header = "Y"){ 
| 		if (/^$/){
| 			$header = "N";
| 		}
| 		next;
| 	}
| 	if (grep(/SOME STRING/,$_)){
| 		printf "\n";
| 	}
| print;
| }

The line beginning "if ($header ..." needs a "eq", not a "=".  Also,
I've never seen the grep operator used for a single entry (not even in
a JAPH :-).  Simply /SOME STRING/ would do it.

Here's something closer to what you want:

#!/usr/bin/perl

while (<>) {
	$header = /^$/..eof ? "N" : "Y";
	print $header;
	print "\f\n" if /SOME STRING/;
	print;
}

Some explanation on that first line: the construct "/^$/..eof" is true
from the first blank line to the end of the file.  This is a handy
idiom, duplicating your logic.  More often, you'll see something like
"1../^$/", which is true from the first line of the file to the first
blank line (not quite the same thing... think of the value *at* the
blank line).

print "Just another Perl hacker,"
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Intel put the 'backward' in 'backward compatible'..."=========/

tchrist@convex.COM (Tom Christiansen) (11/15/90)

In article <27962@sequoia.execu.com> painter@sequoia.execu.com (Tom Painter) writes:

> In the following script, I trying to strip all lines before the first
> blankline from stdin.  In that vein, I set a flag ($header) to "Y"
> and change it to "N" after it hits the blank line.  So far it works.
> However, when I return to the top of the while loop, $header has been changed 
> back to "Y".  The "N" should last for the rest the time, I never want it
> changed back.  Soooo, why does it change back?  It almost looks as if
> the "while" is a little subroutine and it isn't exporting $header globally.
> I did run with "-d" and it never returned to line 3 to reset it.

> Any help appreciated.

> Tom


> #! /usr/bin/perl
> $header = "Y";
> while (<>) {
> print $header;
> 	if ($header = "Y"){ 
> 		if (/^$/){
> 			$header = "N";
> 		}
> 		next;
> 	}
> 	if (grep(/SOME STRING/,$_)){
> 		printf "\n";
> 	}
> print;
> }

That's pretty mangled perl.  You're doing several things wrong, 
like using = for == (or in this case eq), using grep oddly, etc, 
and you're working far too hard.

Your code corrected would be:

    #!/usr/bin/perl
    $header = "Y";
    while (<>) {
	print $header;   # you'll get a lot of Y's here
	if ($header eq "Y") {  
	    if (/^$/) {
		$header = "N";
	    }
	    next;
	}
	if (/SOME STRING/) {
	    print "\n"; # don't bother with printf here
	}
	print;
    }

But that's still way too complex.


    #!/usr/bin/perl
    while (<>) {
	next if 1 .. /^$/;
	print "\f\n" if /SOME_STRING/;
	print;
    }

is one of many ways to express what I think you're trying to do here.

You may also set ($/ = '') to read by paragraphs, if that helps.

You could also have a variable in your loop like this:

    $in_header = 1 .. /^$/;

See the perl man page on the scalar ".." operator for details.

--tom