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.

ysth
  • 96,171
  • 6
  • 121
  • 214
Nate Glenn
  • 6,455
  • 8
  • 52
  • 95
  • 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). – Keith Thompson Jan 25 '13 at 01:13

1 Answers1

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;
ysth
  • 96,171
  • 6
  • 121
  • 214
  • And it once again "breaks" when when I add `undef $fh` at the end of the outer loop. Thanks! – Nate Glenn Jan 25 '13 at 00:47
  • 1
    Perl's little intricacies never cease to amaze me. +1. – friedo Jan 25 '13 at 00:49
  • 8
    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. – hobbs Jan 25 '13 at 01:54