Разбор шестнадцатеричного дампа в perl - PullRequest
5 голосов
/ 05 августа 2010

У меня есть шестнадцатеричный дамп сообщения в файле, который я хочу получить в массиве так что я могу выполнить на нем логику декодирования.
Мне было интересно, если бы это был более простой способ разобрать сообщение, которое выглядит следующим образом.

37 39 30 35 32 34 35 34 3B 32 31 36 39 33 34 35
3B 32 31 36 39 33 34 36 00 00 01 08 40 00 00 15
6C 71 34 34 73 69 6D 31 5F 33 30 33 31 00 00 00
00 00 01 28 40 00 00 15 74 65 6C 63 6F 72 64 69
74 65 6C 63 6F 72 64 69

Обратите внимание, что данные могут содержать до 16 байт в любой строке. Но любая строка также может содержать меньше байтов (минимум: 1)
Есть ли хороший и элегантный способ вместо чтения 2 символов за раз в perl?

Ответы [ 3 ]

6 голосов
/ 05 августа 2010

Я бы прочитал строку за раз, удалил пробел и использовал pack 'H*' для ее преобразования. Трудно быть более конкретным, не зная, какую «логику декодирования» вы пытаетесь применить. Например, вот версия, которая преобразует каждый байт в десятичный:

while (<>) {
  s/\s+//g;
  my @bytes = unpack('C*', pack('H*', $_));
  print "@bytes\n";
}

Вывод из вашего образца файла:

55 57 48 53 50 52 53 52 59 50 49 54 57 51 52 53
59 50 49 54 57 51 52 54 0 0 1 8 64 0 0 21
108 113 52 52 115 105 109 49 95 51 48 51 49 0 0 0
0 0 1 40 64 0 0 21 116 101 108 99 111 114 100 105
116 101 108 99 111 114 100 105
6 голосов
/ 05 августа 2010

Perl имеет оператор hex, который выполняет логику декодирования для вас.

hex EXPR

hex

Интерпретирует EXPR как шестнадцатеричную строку и возвращает соответствующее значение.(Для преобразования строк, которые могут начинаться с 0, 0x или 0b, см. oct.) Если EXPR опущен, используется $_.

print hex '0xAf'; # prints '175'
print hex 'aF'; # same

Помните, что стандартное поведение split разбивает строку на разделители пробелов, например,

$ perl -le '$_ = "a b c"; print for split'
a
b
c

Для каждой строки ввода отделяйте еев шестнадцатеричные значения, преобразуйте значения в числа и push их в массив для последующей обработки.

#! /usr/bin/perl

use warnings;
use strict;

my @values;
while (<>) {
  push @values => map hex($_), split;
}

# for example
my $sum = 0;
$sum += $_ for @values;
print $sum, "\n";

Пример выполнения:

$ ./sumhex mtanish-input 
4196
0 голосов
/ 05 августа 2010

Я думаю, что чтение по двум символам за раз является подходящим способом анализа потока, логические токены которого состоят из двух символов.

Есть ли какая-то причина, по которой вы считаете это уродливым?

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

...