This is the first post of a serie about Japhs
Japhs are crazy-cursed-science, people sometimes love them as much as they hate them 😃
Japhs could be a showcase of obfuscated, bad practices, non modern Perl code but it is also often a demonstration of Perl skills and a way to nicely highlight some features or simply demonstrate code agility.
Several Japhs were written by "Perl Grand Masters".
DO-NOT-DO
Often a Japh is more a matter of obfuscation than encryption.
This is the case of this Japh from Randal Schwartz, where a simple print"Just another Perl hacker,"
is surrounded by "garbage code".
$_='987;s/^(d+)/$1-1/e;$1?eval:print"Just another Perl hacker,"';eval;
This Japh is actually full of nothing 😃
Once unfold, the code is actually very simple but there is some interesting bits here :
- Some fun with
/e
modifier (= evaluate right hand sideRHS
) - A misleading
(d+)
capture (vicious typo : missing\
! 😄) that leads to a$1
actually undefined - Some fun with eval (the Japh killer-feature 😃)
eval {
my $v = "987"; # or my $v = 987; it is the same
# Substitute number by himself minus one
$v =~ s/^(d+)/$1-1/e; # /e enable right hand side as an expression
# $v is (still) "987";
# $1 is undefined
# because to work
# capture (d+) should be (\d+)
if(undef) {
eval;
} else {
print"Just another Perl hacker,";
}
}
I really love this Japh !!
Jump-Jump
$_="krJhruaesrltre c a cnP,ohet";$_.=$1,print$2while s/(..)(.)//;
The trick here is to loop over a string and take one char every 3 chars (but only one time per loop).
Having all keywords sticked together like this :
$_.=$1,print$2while
is a way to exploit the greatness of the parser ! 😎
When I first saw this Japh, I was not sure to understand well s/(..)(.)//
because it seemed the string matched was substitued by nothing.
But is is actually kept by $_.=$1
.
It is the same than this code :
my $str ="krJhruaesrltre c a cnP,ohet";
do {
$str .= $1; # Keep 2 char (..)
print $2; # Print one char (.)
} while($str =~ s/(..)(.)//);
What if we print the $str
to see the content ?
krJhruaesrltre c a cnP,ohet
hruaesrltre c a cnP,ohetkr
aesrltre c a cnP,ohetkrhr
rltre c a cnP,ohetkrhrae
re c a cnP,ohetkrhraerl
c a cnP,ohetkrhraerlre
cnP,ohetkrhraerlrec
P,ohetkrhraerlrec c
hetkrhraerlrec cP,
krhraerlrec cP,he
raerlrec cP,hekr
rlrec cP,hekrra
ec cP,hekrrarl
cP,hekrrarlec
,hekrrarlec c
krrarlec c,h
arlec c,hkr
ec c,hkrar
c,hkrarec
krarecc,
recc,kr
c,krre
rrec,
c,rr
rc,
rc
And if you look closer, you can see the Just another Perl hacker,
hidden like a sort of steganography:
kr[J]hruaesrltre c a cnP,ohet
hr[u]aesrltre c a cnP,ohetkr
ae[s]rltre c a cnP,ohetkrhr
rl[t]re c a cnP,ohetkrhrae
re[ ]c a cnP,ohetkrhraerl
c [a] cnP,ohetkrhraerlre
c[n]P,ohetkrhraerlrec
P,[o]hetkrhraerlrec c
he[t]krhraerlrec cP,
kr[h]raerlrec cP,he
ra[e]rlrec cP,hekr
rl[r]ec cP,hekrra
ec[ ] cP,hekrrarl
c[P],hekrrarlec
,h[e]krrarlec c
kr[r]arlec c,h
ar[l]ec c,hkr
ec[ ]c,hkrar
c,[h]krarec
kr[a]recc,
re[c]c,kr
c,[k]rre
rr[e]c,
c,[r]r
rc[,]
rc
The "substitution per nothing" and the "only one time per loop" tricks are confusing for me.
In my mind, I would have prefered something like this :
my $str ="krJhruaesrltre c a cnP,ohet";
do {
print $2; # Print one char
} while($str =~ s/(..)(.)(.*)/$3$1/);
But one of the goal of a Japh is to confuse the reader, isn't it ?
And this goal is well achieved by this really nice Japh !
Eval-ception
This Japh from Raymond Chen is playing with eval
and \
(protected quotes by antislash).
All the annoying \
, "
and x
makes this line very blurry to the reader.
$_='x"Not ";"x\"another \";\'x\\"perl \\";x\\"hacker,\\"\'"';s/x/print/g;eval eval eval;
It is actually relatively simple when we break down into steps to see what happens exactly :
use v5.10;
$str = 'x"Not ";"x\"another \";\'x\\"perl \\";x\\"hacker,\\"\'"';
$str =~ s/x/print/g;
# 'print"Not "; "print\"another \";\'print\\"perl \\";print\\"hacker,\\"\'"';
say eval $str;
# Not print"another ";'print"perl ";print"hacker,"'
say eval eval $str;
# Not another print"perl ";print"hacker,"
eval eval eval $str;
# Not another perl hacker,
First eval will print Not
and remove "
around the rest of the line :
print"Not ";"print\"another \";'print\"perl \";print\"hacker,\"'"
^ ^
Second eval will print another
and remove '
around the rest of the line :
Not print"another ";'print"perl ";print"hacker,"'
^ ^
Third eval will print perl hacker,
:
Not another print"perl ";print"hacker,"
And finally this is Not another perl hacker
! 😃
The Char-taker
This is a Japh from gnebbia
use Modern::Perl;
say chr($_) foreach qw/
74 117
115 116
20 97
110 111
116 104
101 114
20 80
101 114
108 20
72
97
99
107
101
114/;
Simple and effective !
Not very hard to understand, but it uses some nice features from perl.
The qw
actually drops some formatting for us and builds a clean array of string
.
Then the indentation and spaces are ignored and chr
will tranform ASCII codes into a Japh 😃
use Modern::Perl;
# J u s t a n o t h e r P e r l h a c k e r
foreach my $d (74,117,115,116,20,97,110,111,116,104,101,114,20,80,101,114,108,20,72,97,99,107,101,114) {
print chr($d);
}
This Japh does not really confuse the reader, but force to dig a bit into language understanding, and that's very cool ! 😎
Split-Sort-Grep
Randal Schwartz, in addition of being Japh #0 is one of the master of the Japh competition.
He plays often a lot with split
combined with some other operands, here it is grep
and sort
.
print grep(s/^\d+(.*)/$1 /, sort(split(/ /,"8hacker, 4Perl 1Just 2another")));
I feel comfortable with this one, I see the Japh unordered but there is a sort
not far and numbers will give the ordering 😁
It is a way to properly demonstrate some Perl killer features like easy string manipulation and regular expressions.
We can detail this one liner into an equivalent script :
my $str = "8hacker, 4Perl 1Just 2another";
my @s = split " ", $str;
@s = sort @s;
# 1Just 2another 4Perl 8hacker,
foreach my $v (@s) {
$v =~ s/^\d(.*)/$1/;
print $v . " ";
}
$1
is what is matched between parenthesis.
sort
will not convert to numeric but compare string, if you're not convinced, please check this example :
my $str = "09first 2third 1second";
print join " ", sort split(" ", $str);
That produces :
09first 1second 2third
Despite being relatively simple, this is a cool Japh, demonstrating some nice Perl features. 😃
Turtle Neck
OH! Turtleneck phrase jar! 😲
$_ = "wftedskaebjgdpjgidbsmnjgc";
tr/a-z/oh, turtleneck Phrase Jar!/; print;
This Japh is playing with transliteration operator, the regex range and the default variable $_
features.
The tr
is an operator to translate (like the Unix tr
command line).
a-z
in the regex is actually implicitely transformed into abcdefghijklmnopqrstuvwxyz
.
Then we only have to pick our Japh using the "key" wftedskaebjgdpjgidbsmnjgc
! 😎
Once unfold, the Japh looks like this :
my $str = "wftedskaebjgdpjgidbsmnjgc";
$str =~ tr/abcdefghijklmnopqrstuvwxyz/oh, turtleneck Phrase Jar!/;
print $str;
Relatively simple, but a very cool Japh !
Conclusion
This is the end of my first post about Japhs !
I hope you enjoyed as much as me 😁
Check the next post of the serie
Top comments (5)
Typo in Split-Sort-Grep section: Randal Schwatz.
Fixed thank you a lot 👍
I prefer to make those kind of typo-torial comments in private but it wasn't obvious to me where to send them. My email is first dot last at the google mail address.
Unless I'm just missing something about your profile?
Same email pattern for me 😃
No problem for "public" corrections, I always warmly welcome corrections and I often edit my posts to include some content from comments or even strike through some of my sentences 😝