Как я могу использовать Perl с одной строкой для декодирования строки ASCII, закодированной в шестнадцатеричном формате? - PullRequest
5 голосов
/ 18 февраля 2010

Я бы хотел написать однострочник Perl для декодирования строки символов ASCII, закодированных как шестнадцатеричные числа (например, строка 48 54 54 50 должна быть декодирована как HTTP) Я придумал это:

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

Он печатает пустую строку. Что я делаю не так и как бы ты это написал?

Ответы [ 4 ]

6 голосов
/ 18 февраля 2010

Как всегда с Perl TIMTOWTDI .

Я думал, что предоставлю несколько вариантов и покажу, как они будут выглядеть, если они будут написаны нормально. Если вы хотите узнать больше о параметрах командной строки, perldoc perlrun является полезным ресурсом.


Все они выводят одно и то же. За исключением того, что некоторые из них не выводят символ новой строки в конце.

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'

Ниже приводится пример некоторых примеров, если бы они были написаны нормально. Если вы хотите выяснить, что делают остальные, обязательно посмотрите на perldoc perlrun.


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

Это один довольно прямой. Это, пожалуй, лучший пример здесь, а также самый короткий. Он делает вид, что пробелы используются для разделения строк, поэтому внутри цикла есть только одна буква.

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

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

У этого есть несколько параметров командной строки, которые не делают ничего полезного.

  • Имеется первая опция -0, поэтому -l устанавливает в качестве выходного разделителя пустую строку. Что на самом деле является значением по умолчанию для выходного разделителя.
  • Существует два варианта -p, для которых достаточно одного.
  • Опция -a устанавливает массив @F, но мы на самом деле его не используем.

В основном я использовал -a -l и секунду -p, чтобы в опциях было написано apple . В противном случае это то же самое, что и в предыдущем примере.

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'

Я подумал, что уже написал яблоко , я мог бы также написать lanE .

  • -l не очень полезен, потому что мы уже используем say.
  • Используется -E вместо -e, чтобы мы могли использовать say.
# perl -lanE'say map{chr hex}@F'
$\ = $/; # -l ( output separator set to "\n" )
while( <> ){
  @F = split " ", $_; # -a
  say map { chr hex $_ } @F;
}
6 голосов
/ 18 февраля 2010

Это твой qq/0x$_/ трюк, который не работает.chr ожидает число в качестве аргумента, но получает строковый литерал "0x48".Используйте функцию hex для преобразования 48 в десятичное число, как datageist делает в свой ответ .

Это работает для меня:

echo '48 54 54 50' | perl -nE 'say map(chr, map { hex } split)'
6 голосов
/ 18 февраля 2010

Это работает:

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

Я предполагаю, что вы хотите передать данные из STDIN.

3 голосов
/ 18 февраля 2010

Играть в перлгольф?

-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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...