我正在尝试将变量$num
转换为其反向字节顺序并将其打印出来:
my $num = 0x5514ddb7;
my $s = pack('I!',$num);
print "$s\n";
它打印为一些不可打印的字符,在十六进制编辑器中它看起来是正确的,但是如何才能在控制台上读取它?我已经尝试过了:
print sprintf("%#x\n",$s);
这使得perl抱怨非数字参数,所以我认为pack
返回一个字符串。任何想法如何根据0xb7dd1455
?
$num
答案 0 :(得分:7)
您需要使用unpack
:
my $num = 0x5514ddb7;
my $s = pack('I<!',$num);
my $x = unpack('I>!',$s);
printf("%#x\n",$x);
来自Michael Carman的评论:请注意,字节顺序修饰符(<
和>
)需要Perl v5.10 +。对于旧版本的Perl,您必须使用N
和V
templates代替。
答案 1 :(得分:2)
my $num=0x5514ddb7;
my $i = unpack('N', pack('V',$num));
printf("0x%x\n", $i);
但你确定要这么做吗? 它是32位特定的。 问题是“你为什么问?”为了建议一些比你想要解决的更好的东西。
答案 2 :(得分:2)
您需要使用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
答案 3 :(得分:1)
作为一个主要使用perl的C程序员,我的直觉本能是使用按位运算符进行切片和切块:
$n2 = ($num & 0xff) <<24
| ($num & 0xff00) <<8
| ($num & 0xff0000) >>8
| ($num & 0xff000000) >>24 ;
但是,这是perl,毫无疑问有很多方法可以达到相同的结果,并且可能有一个很好的perl成语。
答案 4 :(得分:0)
我想我会为那些需要检查格式化二进制文件的人提供帮助。这是我在规范以非英特尔字节顺序显示十六进制值时使用的,如MySQL .frm规范。您可以通过增加sysread大小来指定更大的块。打包/解包长度必须是sysread值的2倍。偏移量+ = [设置为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++;
}
答案 5 :(得分:0)
$num = 0x5514ddb7;
print '0x', sprintf( '%08x', $num ) =~ /../g;