How can I parse space separated STDIN hex strings unpacked in Perl?

parsing, perl, unpack

Solution

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]

Problem

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

Original source