Perl implicit close resets the $. variable
Asked Answered
M

1

6

The documentation for Perl's close states that $. isn't reset if you use the implicit close done by open. I was trying to see exactly what this meant, but couldn't get it to happen. Here's my script:

use strict;
use warnings;
use autodie;
my @files = qw(test1.txt test2.txt test3.txt);

#try with implicit close
for my $file (@files){
    open my $fh, '<', $file;
    while(<$fh>){
        chomp;
        print "line $. is $_\n";
    }
    #implicit close here
}

And here are the contents of all three of the files that are read in:

line 1
line 2
line 3
line 4
line 5
line 6
line 7
line 8
line 9
line 10

Since I don't explicitly call close, the implicit close should be used (I think) and $. shouldn't be reset. However, when I run the script, I get this output, showing that $. is reset:

line 1 is line 1
line 2 is line 2
line 3 is line 3
line 4 is line 4
line 5 is line 5
line 6 is line 6
line 7 is line 7
line 8 is line 8
line 9 is line 9
line 10 is line 10
line 1 is line 1
line 2 is line 2
line 3 is line 3
line 4 is line 4
line 5 is line 5
line 6 is line 6
line 7 is line 7
line 8 is line 8
line 9 is line 9
line 10 is line 10
line 1 is line 1
line 2 is line 2
line 3 is line 3
line 4 is line 4
line 5 is line 5
line 6 is line 6
line 7 is line 7
line 8 is line 8
line 9 is line 9
line 10 is line 10

It sure looks like it's being reset to me. Is my understanding of the documentation wrong? Can someone show me under what circumstance the implicit close will not reset $.?

By the way, I'm using Strawberry 5.16.1.

Mitziemitzl answered 25/1, 2013 at 0:39 Comment(1)
The posting software apparently deletes trailing . characters, so your title looked like "Perl implicit close resets $". I "fixed" it by surrounding the $. with backticks (which aren't interpreted in titles, but oh well).Greenery
P
10

$. is not actually a global variable, it is an attribute of the most recently read filehandle. And you are using a new filehandle in each iteration through the loop.

Modifying your code like so "fixes" it:

my $fh;
for my $file (@files){
    open $fh, '<', $file;
Perl answered 25/1, 2013 at 0:42 Comment(3)
And it once again "breaks" when when I add undef $fh at the end of the outer loop. Thanks!Mitziemitzl
Perl's little intricacies never cease to amaze me. +1.Tumulus
The main place this comes into play is with the ARGV filehandle — when you're using <> to read and the file you're reading reaches EOF, perl will re-open ARGV to the next file in @ARGV without an intervening close, so $. will keep counting up. The close ARGV if eof example in perldoc -f eof will catch this condition and put a close between each file so that $. refers to the line position in the current file instead.Popinjay

© 2022 - 2024 — McMap. All rights reserved.