13

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

我怎么能用 Perl 做到这一点?

4

3 回答 3

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

有关更多信息,请参阅perlpacktut

于 2010-03-11T18:43:47.793 回答
8

步骤是:

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

例如:

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);
于 2010-03-11T18:42:29.027 回答
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 函数接受一个模板字符串和一个值列表 [...]

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

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

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

    偏移内容(从左到右增加地址)
         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
                                            | 盒装

也就是说,在我的例子中,$_是一个单一的字符串变量——而pack期望作为输入的几个这样的“单一”变量的列表(除了格式化模板字符串);并再次输出一个“单个”变量(但是,它可能是一个相当大的内存块!)。就我而言,如果输出“单个”变量包含内存中每个字节中的 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...必须指定要编辑的元素数量(否则我们只会返回一个字符);然后,这些替代方案中的任何一个都有效:

$ 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
于 2012-10-26T08:27:10.090 回答