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

发布于 2024-08-24 18:44:32 字数 174 浏览 5 评论 0原文

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

我怎样才能用 Perl 做到这一点?

I have a hex string (length 48 chars) that I want to convert to raw bytes with the pack function in order to put it in a Win32 vector of bytes.

How I can do this with Perl?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

岁吢 2024-08-31 18:44:32
my $bytes = pack "H*", $hex;

有关详细信息,请参阅 perlpacktut

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

See perlpacktut for more information.

醉态萌生 2024-08-31 18:44:32

步骤是:

  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);

The steps are:

  1. Extract pairs of hexadecimal characters from the string.
  2. Convert each pair to a decimal number.
  3. Pack the number as a byte.

For example:

use strict;
use warnings;

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

Or, expressed more compactly:

use strict;
use warnings;

my $string = 'AA55FF0102040810204080';
my @bytes  = map { pack('C', hex($_)) } ($string =~ /(..)/g);
筱武穆 2024-08-31 18:44:32

我有字符串:

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

_(NB:本质上,我想将内存中的上述字节值“转换”为输入,如果通过 hexdump 查看,则将其转换为以下字节值:< /sup>

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

...这就是获取输入十六进制字符串的原始值的方式。
)_

那么,这个打包/解包教程(又名系统如何存储数据事实证明对我来说是最有帮助的,因为它提到:

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

$rec = pack("li 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
                                            |盒子so f

也就是说,在我的例子中,$_ 是一个单个字符串变量 - 而 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

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

$ 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

I have the string:

"61 62 63 64 65 67 69 69 6a"

which I want to interpret as hex values, and display those as ASCII chars (those values should reproduce the character string "abcdefghij").

Typically, I try to write something quick like this:

$ 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

... and then I wonder, why do I get only one character back :)

First, let me note down that the string I have, can also be represented as the hex values of bytes that it takes up in memory:

$ 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

_(NB: Essentially, I want to "convert" the above byte values in memory as input, to these below ones, if viewed by hexdump:

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

... which is how the original values for the input hex string were obtained.
)_

Well, this Pack/Unpack Tutorial (AKA How the System Stores Data) turns out is the most helpful for me, as it mentions:

The pack function accepts a template string and a list of values [...]

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

It returns a scalar containing the list of values stored according to the formats specified in the template [...]

$rec would contain the following (first line in decimal, second in hex, third as characters where applicable). Pipe characters indicate field boundaries.

    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

That is, in my case, $_ is a single string variable -- whereas pack expects as input a list of several such 'single' variables (in addition to a formatting template string); and outputs again a 'single' variable (which could, however, be a sizeable chunk of memory!). In my case, if the output 'single' variable contains the ASCII code in each byte in memory, then I'm all set (I could simply print the output variable directly, then).

Thus, in order to get a list of variables from the $_ string, I can simply split it at the space sign - however, note:

$ 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

... that amount of elements to be packed must be specified (otherwise again we get only one character back); then, either of these alternatives work:

$ 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文