How can I parse space separated STDIN hex strings unpacked in Perl?
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 a开发者_如何学Pythonm 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)?
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 bytesC2
decodes twounsigned char
valuesn7
decodes seven 16-bit big-endian unsigned integers
Output:
$ ./dump-packets [1][7][256][512][7424][0][0][1536][1792]
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.
精彩评论