Как мне разобрать разделенные пробелами шестнадцатеричные строки STDIN, распакованные в Perl? - PullRequest
6 голосов
/ 02 февраля 2010

У меня есть Java-программа, которая выплевывает в шестнадцатеричном формате через пробел 16 необработанных пакетов, полученных по сети.Поскольку я не хочу изменять этот код, я передаю результат в сценарий Perl, который теоретически может просто unpack this из 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!)

Есть лиэлегантный способ использования unpack()?Я не мастер Perl, но другой способ состоит в том, чтобы, как я уже говорил, использовать split, а затем вручную преобразовывать каждый гекс в байт, а затем использовать битовые манипуляции и маски, чтобы получить то, что я хочу.Любые другие предложения (если unpack не спасет день)?

Ответы [ 2 ]

8 голосов
/ 02 февраля 2010

Предполагая, что эти целые числа находятся в порядке с прямым порядком байтов, используйте

#! /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]
3 голосов
/ 02 февраля 2010

Если вы хотите использовать распаковку на распакованных данных, вам нужно сначала упаковать их снова.И вам нужно будет удалить пробелы, прежде чем вы это сделаете.

Другими словами,

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