2010-02-01 7 views
6

Mam program Java, który wypluwa, w formacie szesnastkowym oddzielonym spacjami, 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 przekształcić to w STDIN w rozpoznawalne zmienne. Poniżej znajduje się próbka wejścia liniowego do mojego Perl pliku:Jak można sparsować oddzielone spacjami ciągi heksadecymalne STDIN rozpakowane w Perlu?

 
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 char/bajt, int do zmiennej 16bit całkowitej)

I początkowo chciał użyć unpack do czysto oddzielić wejście dopasować do zmiennych, których potrzebowałem. Jednak z powodu ogranicznika 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 korzystania z unpack()? Nie jestem mistrzem Perla, ale innym sposobem jest, jak już sugerowałem, użycie split, a następnie ręczna zamiana każdego heksa na bajt, a następnie użycie manipulacji bitami i masek, aby uzyskać to, czego chcę. Wszelkie inne sugestie (jeśli unpack nie zapisuje dnia)?

Odpowiedz

8

Zakładając te ints są w kolejności 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. Szablon unpack ma następujące części:

  • x5 pomija pięć bajtów
  • C2 dekoduje dwa unsigned char wartości
  • n7 dekoduje siedem 16-bitowych grubokońcej liczby całkowite

wyjściowa:

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

Możesz sprawić, że będzie ładniej wyglądać, mówiąc: 'map {hex} split' :) – friedo

+2

Albo nawet po prostu' map hex, split' - prawie Haskell! –

+0

faktycznie potwierdziłem, że bajty są w małym endianie. dziwne, ponieważ są wysyłane przez sieć, pomyślałem, że powinien być w porządku sieciowym. No cóż, jedyną zmianą musi być rozpakowanie "x5C2n7", aby rozpakować "x5C2v7", prawda? I dzięki za odpowiedź ... to forum jest niesamowite – intiha

3

Jeśli chcesz rozpakować dane po rozpakowaniu, musisz najpierw spakować je ponownie. Musisz 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. 
+0

Ja naprawdę u W tym rozwiązaniu ze względu na jego czystszy wygląd (zrozumiałem, co robi kod) w połączeniu z rozpakowaniem sugerowanym powyżej. i mogę także parsować wiersz $, jeśli kod java wypisze ciąg znaków błędu. – intiha

Powiązane problemy