35

How can I use __DATA__ twice?

#!/usr/local/bin/perl
use warnings;
use 5.012;

while ( <DATA> ) {
    print;
}

while ( <DATA> ) {
    chomp if $. == 1;
    print scalar reverse;
    print "\n" if eof;
}
__DATA__
one
two
three
four
five
six
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
sid_com
  • 24,137
  • 26
  • 96
  • 187

3 Answers3

53

To use the DATA filehandle twice you need to rewind it. The tricky bit is that if you do seek(DATA, 0, 0), it'll be positioned to the first source line, not the line after __DATA__. Therefore you need to save the position first:

my $data_start = tell DATA; # save the position
print while (<DATA>);
seek DATA, $data_start, 0;  # reposition the filehandle right past __DATA__
print while (<DATA>);

See also:

Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
7

You can use the Data::Handle module to do the tell()ing and seek()ing for you behind the scenes. (Though I believe if you have perl 5.10 or later you can dup the DATA file handle instead of sharing the original DATA file handle and seeking back and forth in it.)

John Siracusa
  • 14,971
  • 7
  • 42
  • 54
  • you can dup (or fdopen) DATA in perl's other than 5.10, but it seems like only 5.8.9 ((and possibly other versions between, but not including 5.8.0 and 5.10.0) lets you keep separate pointers per file-handle. So you still need to seek back and forth on your duped filehandle, or just use Data::Handle. – MkV Dec 19 '10 at 07:05
-1

In all honesty, the easiest solution is to read DATA once and stash it in an array or variable.

my @data;
while(<DATA>){
  push @data, $_;
}
Tom Melly
  • 353
  • 1
  • 8
  • Depends. If you do not want to store it, this is not an option. – stephanmg Dec 10 '19 at 13:36
  • Why would you not want to store it? It's already in the script in any event, and if later you want to switch to another source (e.g. an input file), then this approach will make modifying the script much simpler. – Tom Melly Dec 12 '19 at 08:12