如何解析在 Perl 中解压的空格分隔的 STDIN 十六进制字符串?

发布于 2024-08-20 02:08:37 字数 617 浏览 5 评论 0原文

我有一个 Java 程序,它以空格分隔的十六进制格式吐出通过网络接收的 16 字节原始数据包。由于我不想更改该代码,因此我将结果通过管道传递给 Perl 脚本,理论上,该脚本可以简单地将其从 STDIN 解压为可识别的变量。以下是我的 Perl 文件的行输入示例:

FF FF 09 7D 10  01  07  01 00  02 00  1D 00  00 00  00 00  06 00  07 00 
|--garbage-----|c--|c--|int---|int---|int---|int---|int---|int---|int---|

(c 代表 char/byte,int 代表 16 位整数变量)

我最初想使用 unpack 将每个输入行干净地分离为变量我需要。但是,由于字符串中的空格分隔,我不确定如何处理它(我可以使用“A”作为模板,但我也可能只使用 split!)

有没有一种优雅的方式使用 解压()?我不是 Perl 大师,但另一种方法是,正如我之前建议的那样,使用 split ,然后手动将每个十六进制转换为字节,然后使用位操作和掩码来获得我想要的。还有其他建议吗(如果 unpack 不能挽救局面)?

I have a Java program that spits out, in space-separated hexadecimal format, 16 bytes of raw packet received over the network. Since I dont want to change that code, I am piping the result to a Perl script that, theoretically, can simply unpack this from STDIN into recognizable variables. The following is a sample of the line input to my Perl file:

FF FF 09 7D 10  01  07  01 00  02 00  1D 00  00 00  00 00  06 00  07 00 
|--garbage-----|c--|c--|int---|int---|int---|int---|int---|int---|int---|

(c is for char/byte, int for 16bit integer variable)

I initially wanted to use unpack to cleanly separate each input line into variables that I needed. However, because of the space delimit in the string, I am not sure how to handle it (I can use 'A' as a template, but then I might as well just use split!)

Is there a elegant way of using unpack()? I am not a Perl master, but the other way is to, as I suggested before, use split and then manually convert each hex to a byte, and then use bit manipulations and masks to get what I want. Any other suggestions (if unpack doesnt save the day)?

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

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

发布评论

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

评论(2

森末i 2024-08-27 02:08:37

假设这些 int 是大端顺序, use

#! /usr/bin/perl

use warnings;
use strict;

# for demo only
*ARGV = *DATA;

while (<>) {
  my @fields = unpack "x5C2n7",
               pack "C*",
               map hex, split;

  print "[", join("][" => @fields), "]\n";
}

__DATA__
FF FF 09 7D 10 01 07 01 00 02 00 1D 00 00 00 00 00 06 00 07 00

它首先根据它们的值打包字节 (C*)。 unpack 模板包含以下部分:

  • x5 跳过五个字节
  • C2 解码两个 unsigned char
  • n7 解码七个 16 位大端无符号整数

输出:

$ ./dump-packets
[1][7][256][512][7424][0][0][1536][1792]

Assuming those ints are in big-endian order, use

#! /usr/bin/perl

use warnings;
use strict;

# for demo only
*ARGV = *DATA;

while (<>) {
  my @fields = unpack "x5C2n7",
               pack "C*",
               map hex, split;

  print "[", join("][" => @fields), "]\n";
}

__DATA__
FF FF 09 7D 10 01 07 01 00 02 00 1D 00 00 00 00 00 06 00 07 00

It starts off by packing in the bytes (C*) according to their values. The unpack template has the following parts:

  • x5 skips five bytes
  • C2 decodes two unsigned char values
  • n7 decodes seven 16-bit big-endian unsigned integers

Output:

$ ./dump-packets
[1][7][256][512][7424][0][0][1536][1792]
假装不在乎 2024-08-27 02:08:37

如果您想对未打包的数据使用 unpack,则需要先将其再次打包。在执行此操作之前,您需要删除空格。

换句话说,

$line =~ tr/ //d;          # remove spaces
$line = pack 'H*', $line;  # convert hex to binary
# Now you can use unpack.

If you want to use unpack on unpacked data, you'll need to pack it again first. And you'll need to remove the spaces before you do that.

In other words,

$line =~ tr/ //d;          # remove spaces
$line = pack 'H*', $line;  # convert hex to binary
# Now you can use unpack.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文