/ / Jak mogę sparsować oddzielone spacjami ciągi heksadecymalne STDIN rozpakowane w Perlu? - perl, parsowanie, rozpakowanie

Jak mogę sparsować oddzielone spacjami ciągi heksadecymalne STDIN rozpakowane w Perlu? - perl, parsowanie, rozpakowanie

Mam program Java, który wypluwa, woddzielony spacjami format szesnastkowy, 16 bajtów surowego pakietu odebranego przez sieć. Ponieważ nie chcę zmieniać tego kodu, przesyłam wynik do skryptu Perla, który teoretycznie może po prostu unpack to z STDIN w rozpoznawalne zmienne. Poniżej znajduje się próbka wejścia liniowego do mojego pliku 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 jest dla char / byte, int dla 16-bitowej zmiennej liczbowej)

Początkowo chciałem użyć unpack do czystego rozdzielenia każdej linii wejściowej nazmienne, których potrzebowałem. Jednak ze względu na ograniczenie przestrzeni w łańcuchu, nie jestem pewien jak sobie z tym poradzić (mogę użyć "A" jako szablonu, ale mogę równie dobrze użyć podziału!)

Czy istnieje elegancki sposób użycia unpack()? Nie jestem mistrzem Perla, ale innym sposobem jest, jak już sugerowałem, używanie split a następnie ręcznie przekonwertuj każdy heks na bajt, a następnie użyj manipulacji bitami i masek, aby uzyskać to, czego chcę. Wszelkie inne sugestie (jeśli unpack nie oszczędzasz dnia)?

Odpowiedzi:

8 dla odpowiedzi № 1

Zakładając, że te int są w porządku big-endian, użyj

#! /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

Zaczyna się od pakowania w bajtach (C*) zgodnie z ich wartościami. The unpack szablon ma następujące części:

  • x5 Pomija pięć bajtów
  • C2 dekoduje dwa unsigned char wartości
  • n7 dekoduje siedem 16-bitowych liczb całkowitych bez znaku big-endian

Wydajność:

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

3 dla odpowiedzi № 2

Jeśli chcesz rozpakować dane po rozpakowaniu, musisz najpierw spakować je ponownie, a będziesz musiał usunąć spacje, zanim to zrobisz.

Innymi słowy,

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