开发者

How can I use a Perl one-liner to decode an ASCII string encoded in hex?

开发者 https://www.devze.com 2022-12-20 18:04 出处:网络
I’d like to write a Perl one-liner to decode a line of ASCII characters encoded as hexadecimal numbers (for example the line 48 54 54 50 should be decoded as HTTP). I came up with t开发者_开发问答his

I’d like to write a Perl one-liner to decode a line of ASCII characters encoded as hexadecimal numbers (for example the line 48 54 54 50 should be decoded as HTTP). I came up with t开发者_开发问答his:

perl -nE 'say map(chr, map { qq/0x$_/ } split)'

It prints an empty line. What am I doing wrong and how would you write it?


It's your qq/0x$_/ trick that doesn't work. chr expects a number as argument, but gets the string literal "0x48". Use the hex function to convert 48 to a decimal number, like datageist does in his answer.

This works for me:

echo '48 54 54 50' | perl -nE 'say map(chr, map { hex } split)'


This works:

echo '48 54 54 50' | perl -nE 'say map{chr(hex)} split'

I’m assuming you want to feed the data from STDIN.


As always with Perl TIMTOWTDI.

I thought I would submit several options, and show what they would look like if they were written normally. If you want to know more about the command line options perldoc perlrun is a useful resource.


These all output the same thing. With the exception that some of them don't print a newline on the end.

echo '48 54 54 50' | perl -0x20 -pe'$_=chr hex$_'
echo '48 54 54 50' | perl -0x20 -ne'print chr hex$_'
echo '48 54 54 50' | perl -0777 -anE'say map chr,map hex,@F'
echo '48 54 54 50' | perl -0777 -anE'say map{chr hex$_}@F'
echo '48 54 54 50' | perl -0apple'$_=chr hex$_' -0x20
echo '48 54 54 50' | perl -apple'$_=join"",map{chr hex}@F'
echo '48 54 54 50' | perl -lanE'say map{chr hex}@F'

The following is what some of the examples would look like if they were written normally. If you want to figure out what the rest of them do, definitely look at perldoc perlrun.


perl -0x20 -pe'$_=chr hex$_'

This is one is fairly straight forward. It is perhaps the best example here, and is also the shortest one. It pretends that spaces are used to separate lines, so that there is only one letter to deal with inside of the loop.

# perl -0x20 -pe'$_=chr hex$_'
$/ = " ";  # -0 ( input separator )
while( <> ){
  $_ = chr hex $_;
} continue {
  print $_;
}

perl -0apple'$_=chr hex$_' -0x20

This one has a few command line options that don't do anything useful.

  • The first -0 option is there so that -l sets the output separator to an empty string. Which is actually the default for the output separator.
  • There are two -p options where one would have sufficed.
  • The -a option sets up the @F array, but we don't actually use it.

Basically I used -a -l and a second -p so that the options would spell apple. Otherwise this one is the same as the last example.

echo '48 54 54 50' | perl -0x20 -pe'$_=chr hex$_'
# perl -0apple'$_=chr hex$_' -0x20
$/ = "";  # -0 ( input separator )
$\ = $/;  # -l ( output separator )
$/ = " "; # -0x20 ( input separator )
while( <> ){
  @F = split " ", $_; # -a ( unused )
  $_ = chr hex $_;
} continue {
  print $_;
}

perl -lanE'say map{chr hex}@F'

I figured I already spelled apple, I might as well spell lanE.

  • -l isn't really useful, because we already are using say.
  • Used -E instead of -e so that we could use say.
# perl -lanE'say map{chr hex}@F'
$\ = $/; # -l ( output separator set to "\n" )
while( <> ){
  @F = split " ", $_; # -a
  say map { chr hex $_ } @F;
}


Play perlgolf?

-ple y/0-9A-Fa-f//cd;$_=pack"H*",$_
-ple $_=pack"H*",$_,join"",split
-nE say map chr hex,split
-naE say map chr hex,@F
0

精彩评论

暂无评论...
验证码 换一张
取 消