如何使用Perl将48十六进制字符串转换为字节?

时间:2010-03-11 18:18:51

标签: perl pack

我有一个十六进制字符串(长度为48个字符),我希望使用pack函数将其转换为原始字节,以便将其放入Win32矢量字节中。

如何使用Perl执行此操作?

3 个答案:

答案 0 :(得分:25)

my $bytes = pack "H*", $hex;

有关详细信息,请参阅perlpacktut

答案 1 :(得分:6)

步骤如下:

  1. 从字符串中提取十六进制字符对。
  2. 将每对转换为十进制数。
  3. 将数字打包为一个字节。
  4. 例如:

    use strict;
    use warnings;
    
    my $string = 'AA55FF0102040810204080';
    my @hex    = ($string =~ /(..)/g);
    my @dec    = map { hex($_) } @hex;
    my @bytes  = map { pack('C', $_) } @dec;
    

    或者,表达得更紧凑:

    use strict;
    use warnings;
    
    my $string = 'AA55FF0102040810204080';
    my @bytes  = map { pack('C', hex($_)) } ($string =~ /(..)/g);
    

答案 2 :(得分:1)

我有字符串:

61 62 63 64 65 67 69 69 6a

我想将其解释为十六进制值,并将其显示为ASCII字符(这些值应该重现字符串“abcdefghij”)。

通常情况下,我会尝试像这样快速写一些东西:

$ echo "61 62 63 64 65 67 69 69 6a" | perl -ne 'print "$_"; print pack("H2 "x10, $_)."\n";'
61 62 63 64 65 67 69 69 6a
a

...然后我想知道,为什么我只回到一个角色:)

首先,让我记下我所拥有的字符串,也可以表示为内存中占用的字节的十六进制值:

$ echo -n "61 62 63 64 65 67 68 69 6a" | hexdump -C
00000000  36 31 20 36 32 20 36 33  20 36 34 20 36 35 20 36  |61 62 63 64 65 6|
00000010  37 20 36 38 20 36 39 20  36 61                    |7 68 69 6a|
0000001a

_(注意:基本上,我想将内存中的上述字节值“转换”为输入,如果由hexdump查看,则将这些值转换为以下字节值:

$ echo -n "abcdefghij" | hexdump -C
00000000  61 62 63 64 65 66 67 68  69 6a                    |abcdefghij|
0000000a

...获取输入十六进制字符串的原始值。 )_

嗯,这个Pack/Unpack Tutorial (AKA How the System Stores Data)对我来说是最有帮助的,正如它提到的那样:

  

pack函数接受模板字符串和值列表[...]

     

$rec = pack( "l i Z32 s2", time, $emp_id, $item, $quan, $urgent);

     

它返回一个标量,其中包含根据模板中指定的格式存储的值列表[...]

     

$rec将包含以下内容(第一行为十进制,第二行为十六进制,第三行为适用的字符)。管道字符表示字段边界。

    Offset   Contents (increasing addresses left to right)
         0   160  44  19  62| 41  82   3   0| 98 111 120 101 115  32 111 102
              A0  2C  13  3E| 29  52  03  00| 62  6f  78  65  73  20  6f  66
                                            |  b   o   x   e   s       o   f

也就是说,在我的情况下,$_是一个单个字符串变量 - 而pack期望输入一个列表的几个这样的'single'变量(除了格式化模板字符串);并输出一个'单个'变量(但是,它可能是一个相当大的内存块!)。在我的例子中,如果输出'single'变量在内存中的每个字节中包含ASCII代码,那么我就完全设置了(我可以直接打印输出变量,然后)。

因此,为了从$_字符串中获取变量列表,我可以在空格符号上split - 但请注意:

$ echo "61 62 63 64 65 67 68 69 6a" | perl -ne 'print "$_"; print pack("H2", split(/ /, $_))."\n";'
61 62 63 64 65 67 68 69 6a
a

......必须指定要pack ed的元素数量(否则我们只返回一个字符);那么,这些替代方案中的任何一个都有效:

$ echo "61 62 63 64 65 67 68 69 6a" | perl -ne 'print "$_"; print pack("H2"x10, split(/ /, $_))."\n";'
61 62 63 64 65 67 68 69 6a
abcdeghij

$ echo "61 62 63 64 65 67 68 69 6a" | perl -ne 'print "$_"; print pack("(H2)*", split(/ /, $_))."\n";'
61 62 63 64 65 67 68 69 6a
abcdeghij