regex - 如何在 Perl 中将十六进制解码为负整数值

标签 regex perl hex

我有以下十六进制数据格式:

9BDCE310
B4D9F1E502
EAB1A9C607
88EE8EB9F9FFFFFFFF01
9E828D89FCFFFFFFFF01

通常,我使用以下代码解码回整数:

sub decodeInt
{
    $_[0] =~ s/^([\x80-\xFF]*[\x00-\x7F])// or return;

    my $encoded_num = $1;
    my $num = 0;
    for ( reverse unpack 'C*', $encoded_num )
    {
        $num = ( $num << 7 ) | ( $_ & 0x7F );
    }

    return $num;
}

但它不适用于带符号的负整数值(最后 2 个数据)。

88EE8EB9F9FFFFFFFF01
9E828D89FCFFFFFFFF01

请帮我修改一下代码

最佳答案

我猜解码后的值是一个转换为无符号的 64 位有符号二进制补码整数。在二进制补码机上,您可以使用以下命令将其强制转换:

$num = unpack 'q', pack 'Q', $num;

例如,

use strict;
use warnings;
use feature qw( say );

use Config qw( %Config );

sub decode_int {
    my ($encoded_num) = @_;

    my $num = 0;
    $num = ( $num << 7 ) | ( $_ & 0x7F )
       for reverse unpack 'C*', $encoded_num;

    $num = unpack 'q', pack 'Q', $num;

    return $num;
}

{
   $Config{ivsize} >= 8 && $Config{uvsize} >= 8
      or die("64-bit int support required\n");

   say decode_int(pack('H*', $_))
      for qw(
         9BDCE310
         B4D9F1E502
         EAB1A9C607
         88EE8EB9F9FFFFFFFF01
         9E828D89FCFFFFFFFF01
      );
}

输出

35188251
750546100
2026526954
-1759267064
-1054654178

请注意,所使用的编码方案对于有符号数来说效率非常低。

关于regex - 如何在 Perl 中将十六进制解码为负整数值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59333036/

相关文章:

c++ - Htoi 10 位数字的输出不正确

c++ - 多维数组打印十六进制数字而不是数组的内容。为什么?

javascript - 使用正则表达式进行一元运算符拆分

php - preg_replace 删除特殊字符

java - 我不能使用像这样的组名 "abc_def"使用模式

javascript - 使用正则表达式从文本中获取字符串

perl - Grep -> 如何替换文本文件的内容

javascript - 减轻 javascript 中的十六进制代码

regex - Perl 正则表达式 : Match this or that but NOT the other

perl - perl查询ISODate时间