in reply to Seekers of Perl Obfuscation
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:
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.1 2 3 ---- #!/usr/bin/perl print <DATA>; print "\n----\n"; seek(DATA,0,0); print <DATA>; __END__ 1 2 3
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
|
|---|