Как напечатать переменную в обратном порядке байтов? - PullRequest
4 голосов
/ 03 июня 2010

Я пытаюсь преобразовать переменную $num в обратный порядок байтов и распечатать ее:

my $num = 0x5514ddb7;
my $s = pack('I!',$num);
print "$s\n";

Она печатается как некоторые непечатаемые символы, и в шестнадцатеричном редакторе она выглядит правильно,но как я могу сделать его читаемым на консоли?Я уже пробовал это:

print sprintf("%#x\n",$s);

Это заставляет Perl жаловаться на нечисловой аргумент, поэтому я думаю, pack возвращает строку.Любые идеи, как я могу распечатать 0xb7dd1455 на консоли, на основе $num?

Ответы [ 6 ]

7 голосов
/ 03 июня 2010

Вам нужно использовать unpack:

my $num = 0x5514ddb7;
my $s = pack('I<!',$num);
my $x = unpack('I>!',$s);
printf("%#x\n",$x);

Комментарий от Майкл Карман : Помните, что для модификаторов порядка байтов (< и >) требуется Perl v5.10 +. Для более старых версий Perl вам придется использовать шаблоны N и V .

2 голосов
/ 03 июня 2010

Вам необходимо использовать CORE::unpack() "H" (заглавная H):

H   A hex string (high nybble first).

my $num=0x5514ddb7;
my $s=pack('I!',$num);
print unpack ("H*", "$s") . "\n"; # b7dd1455
2 голосов
/ 03 июня 2010
my $num=0x5514ddb7;
my $i = unpack('N', pack('V',$num));
printf("0x%x\n", $i);

Но вы уверены, что хотите это сделать? Это 32-битный характер. Вопрос напрашивается для «почему ты спрашиваешь?» чтобы предложить что-то лучшее, чем то, что вы пытаетесь решить.

1 голос
/ 03 июня 2010

Как программист в основном на C, который работает на Perl, мои непосредственные инстинкты заключаются в нарезке и нарезке кубиками с помощью побитовых операторов:

$n2 = ($num & 0xff) <<24
    | ($num & 0xff00) <<8
    | ($num & 0xff0000) >>8
    | ($num & 0xff000000) >>24 ;

Но, поскольку это Perl, есть, несомненно, много способов достичь того же результата, и, вероятно, есть хорошая идиома Perl для этого.

0 голосов
/ 23 августа 2013
$num = 0x5514ddb7;
print '0x', sprintf( '%08x', $num ) =~ /../g;
0 голосов
/ 23 августа 2013

Я подумал, что я должен вмешаться для тех из нас, кому нужно проверить отформатированные двоичные файлы. Это то, что я использую, когда спецификация показывает шестнадцатеричные значения в байтовом порядке не-Intel, как MySQL .frm. Вы можете указать большие куски, увеличив размер sysread. Длина упаковки / распаковки должна быть в 2 раза больше значения sysread. Смещение + = [установить значение sysread].

#!/usr/bin/perl
BEGIN {
    use Getopt::Long;

    $reverse=0;
    GetOptions ("reverse" => \$reverse);

}

my $f=STDIN;
if (int(@ARGV))
{
    open(IN, $ARGV[0]) or die "Failed to open $ARGV[0] for reading.\n$!";
    $f=IN;
}

my $count=1;
my $offset=0;
my $after_nl=1;
while (sysread($f,$buf,2))
{
    my $hex = unpack('H4', $buf);
    $hex=join("",(split(//,$hex))[2,3,0,1]) unless $reverse;
    if (($count % 8) == 0)
    {
        printf "%s\n", $hex;
        $after_nl=1;
        $offset += 2;
    }
    else
    {
        printf "%08x ", $offset if $after_nl;
        printf "%s ", $hex;
        $offset += 2;
        $after_nl=0;
    }

    $count++;
}
...