Hmm, truly fascinating stuff. For those that are interested here is an explanation and some code snippets
#!/usr/bin/perl
print <DATA>;
print "\n----\n";
seek(DATA,0,0);
print <DATA>;
__END__
1
2
3
When you run this you see two interesting things:
1
2
3
----
#!/usr/bin/perl
print <DATA>;
print "\n----\n";
seek(DATA,0,0);
print <DATA>;
__END__
1
2
3
First the data after the __END__ tag is read and printed.
I used to think you had to use __DATA__ Evidently not. Next the SEEK resets the pointer not to the begining of the
special file handle __END__ but to the begining of the file! Personally I would call this a *bug* but one mans bug is
another man's feature.
Next consider this code
#!/usr/bin/perl
seek(DATA,0,0);
print map{$. . $_}<DATA>;
__END__
This prints:
5#!/usr/bin/perl
5
5seek(DATA,0,0);
5print map{$. . $_}<DATA>;
5__END__
So within the map $. (the line number special var) is always 5 (the total lines)
Now consider this:
#!/usr/bin/perl -w
seek(DATA,0,0);
*a=*.;
print map{$a-=1;$..$_}<DATA>;
__END__
This prints:
C:\>perl test4.pl
5#!/usr/bin/perl -w
4
3seek(DATA,0,0);
2*a=*.;
1print map{$a-=1; $. . $_}<DATA>;
0__END__
Ahha so the glob assignment *a=*. does several things. Initially in the map $a is set to $. so $a=5.
We then decrement $a which changes $.
Finally consider this:
#!/usr/bin/perl -w
use strict;
#Just
#Another
#Perl
#Hacker
seek(DATA,0,0);
*a=*.;
print map{$a-=chomp;s/.//; "$.\t$_\n" }<DATA>;
__END__
This prints:
12 !/usr/bin/perl -w
11
10 se strict;
9
8 Just
7 Another
6 Perl
5 Hacker
4
3 eek(DATA,0,0);
2 a=*.;
1 rint map{$a-=chomp;s/.//; "$.\t$_\n" }<DATA>;
0 _END__
So now we can do a deconstruct:
#!/usr/bin/perl -w
use strict;
#Just # our data
#Another
#Perl
#Hacker
seek(DATA,0,0); # seek the begining of the file
*a=*.; # glob assignment
warn # same effect as print but includes the line num
map{
$a-=chomp # chomp return num chars chomped (1) thus $a -= 1
, # comma op could be ; without changing result
s # substitute
<.> # first char on line
;q<''>; # with an expression that evals to null
eieio # the /ee makes second part eval to null
# the /i (ignore case) does not matter.
# and the /o compiles once
# put them together and you have:
# Old Macdonald Had A JAPH E I E I O
; # yeah well if you need this explained....
$.<8&&$.>2?"$_ ":''# this is ($. < 8 and $. > 2) ? "$_ " : "",
# we actually only need lines 5-8 (see above)
} # close map
<DATA>; # map data array (whole file)
__END__
cheers
tachyon |