【问题标题】:How can I convert hex strings into numbers in Perl?如何在 Perl 中将十六进制字符串转换为数字?
【发布时间】:2010-12-04 15:46:12
【问题描述】:

我最近编写了一个脚本来解析单个二进制字节月份字段的文本表示。

(别问:-{)

在摆弄 sprintf 一段时间后,我放弃了,这样做了;

our %months = qw / x01 1 
       x02 2
       x03 3 
       x04 4 
       x05 5 
       x06 6 
       x07 7 
       x08 8 
       x09 9 
       x0a 10 
       x0b 11 
       x0c 12 /;
...
my $month = $months{$text};

我侥幸逃脱,因为我只使用 12 个数字,但有更好的方法吗?

【问题讨论】:

  • 您的意思是0x1 而不是x01
  • @Nathan 在这种特殊情况下不,但在非疯狂的情况下,您可能会想要 0x01,但您的回答涵盖了这两种情况,这就是我接受它的原因!
  • 反之,十进制转十六进制,请参阅 Stack Overflow 问题 How to convert decimal to hexadecimal in Perl

标签: perl hex


【解决方案1】:

如果你有

$hex_string = "0x10";

你可以使用:

$hex_val = hex($hex_string);

你会得到:$hex_val == 16

hex 不需要字符串开头的“0x”。如果它丢失,它仍然会将十六进制字符串转换为数字。

您还可以使用oct 将二进制、八进制或十六进制字符串转换为基于前缀的数字:

  • 0b - 二进制
  • 0 - 八进制
  • 0x - 十六进制

【讨论】:

  • 当你知道答案时,它是如此明显:-)
【解决方案2】:

请参阅hex 和/或oct

#!/usr/bin/perl

use strict;
use warnings;

my @months = map hex, qw/x01 x02 x03 x04 x05 x06 x07 x08 x09 x0a x0b x0c/;
print "$_\n" for @months;

【讨论】:

  • 要说明:“say”是最近 perls 添加的(恕我直言有问题的)新语法之一。默认情况下它不起作用,因为作为新语法它会破坏旧脚本。因此,您使用“-E”参数来运行具有“所有”功能的脚本。但是,这当然会为您添加所有功能,因为您的脚本也是编写的,这可能会破坏它。基本上,给定的示例更多的是炫耀,而不是设计解决方案。但是关于 hex 函数的答案是对的。
  • @Andy Ross:没有炫耀。可以只使用print "$_\n" 而不是say。然而,在第一个示例的情况下,使用 print 将需要我写 print qq{$_\n},这显然更加混乱。这两个示例都是为了复制和粘贴到命令提示符而编写的,仅供说明之用。没有脚本可以破坏。如果只想在自己的脚本中使用say,可以使用use feature 'say'use Perl6::Say(在CPAN 上可用)。最后,什么工程解决方案???
  • 我的观点更多的是关于 -E 而不是说。 -E 参数不能可靠地用于任何事情,因为它没有指定特定的语言,只是“最新的”。而且我不遵循您的引用论点。您可以在命令行上将双引号括在单引号内...
  • @Andy Ross 对你的两个 cmets 的简单解读让我感到困惑。但是,人生太短暂了。不再有-E,不再有say,尽管我认为你的批评是空洞的。
【解决方案3】:

如果我理解正确,您每月有 1 个字节 - 不是字符串“0x10”,而是包含 10 个字节的字节。

这样的话,你应该使用unpack:

my $in = "\x0a";
print length($in), "\n";
my ($out) = unpack("c", $in);
print length($out), "\n", $out, "\n"

输出:

1
2
10

如果输入的是3个字符,比如“x05”,那么修改也很简单:

my $in = "x0a";
my $out = hex($in);

【讨论】:

  • @depesz 您的反对票完全没有道理。你知道qw// 运算符在 Perl 中的作用吗?你知道单个二进制字节的文本表示是什么意思吗?
  • @Sinan:我知道。我猜 OP 给了 \x01,而不是 x01 - 而且 \ 只是在某个地方丢失了。请注意他的问题:“单二进制字节月份字段”。不是“4 字节字符串 \x01”或“3 字节字符串”
  • @depesz 文本表示单个二进制字节月份字段。单词必须意味着什么。
  • @Sinan - 好的。现在你让我怀疑了。相应地删除了反对票。
【解决方案4】:

这是另一种可能更实用的直接转换字符串中包含的十六进制的方法。

这利用了 s/// 上的 /e(e 表示评估)正则表达式修饰符。

从这个字符串开始:

$hello_world = "\\x48\\x65\\x6c\\x6c\\x6f\\x20\\x57\\x6f\\x72\\x6c\\x64";

十六进制转字符:

print $hello_world =~ s/\\x([0-9a-fA-F]{2})/chr hex $1/gre;

十六进制转十进制数:

print $hello_world =~ s/\\x([0-9a-fA-F]{2})/hex $1/gre;

删除 /r 修饰符以就地替换字符串。

有一天,我使用了一个处理二进制文件的 python 脚本,但我被一个只包含十六进制数字的字节文字 (b'\x09\xff...') 困住了。 我设法用一个作为上述变体的单行来取回我的字节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-19
    • 2013-02-07
    • 2019-10-04
    • 2017-04-05
    • 2017-08-23
    • 2011-05-15
    • 2018-01-31
    相关资源
    最近更新 更多