4

Perl seems to be killing my array whenever I read a file:

my @files = ("foo", "bar", "baz");
print "Files: " . join(" ", @files) . "\n";

foreach(@files) {
   print "The file is $_\n";
   func();
}

sub func {
   open(READ, "< test.txt");
   while(<READ>) {
   }
   close READ;
}

print "Files: " . join(" ", @files) . "\n";

produces:

Files: foo bar baz
The file is foo
The file is bar
The file is baz
Files:

but when I comment out func(), it gives what I would've expected:

Files: foo bar baz
The file is foo
The file is bar
The file is baz
Files: foo bar baz

Any ideas why this might be happening?

1 Answer 1

12

You have to change foo to localize $_, or not to use $_ in your loop. Best yet, do both:

foreach my $filename (@files) {
    print "The file is $filename\n";
    func();
}

sub func {
    local $_;
    open my $read, '<', 'test.txt' or die "Couldn't open test.txt: $!";
    while(<$read>) {
    }
    close $read or die "Couldn't close file: $!";
}

The foreach loop aliases $_ to the current name of the file and the while(<READ>) assigns to $_. That's a bad combination of magic, so to say.

In general, it's a bad idea to rely on much on $_ for anything other than a one-liner.

Sign up to request clarification or add additional context in comments.

3 Comments

my $_; (5.10+ only) is a better way to do it
True, but distributions are only beginning to move to 5.10. I assume people are still on 5.8 for the most part.
Brad: that is correct, but personally I'm only using it since last week, so I'm not assuming other people are also using it. My Debian machines don't have it yet, for example. For that matter, plenty of people are still stuck on Perl 5.6 :-|.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.