2010-02-01 3 views
6

Ich habe ein Java-Programm, das im hexadezimalen Format mit Leerzeichen getrennt 16 Byte des über das Netzwerk empfangenen Rohpakets ausspuckt. Da ich diesen Code nicht ändern möchte, übergebe ich das Ergebnis an ein Perl-Skript, das theoretisch von STDIN in erkennbare Variablen unpack kann. Das Folgende ist eine Probe von dem Line-Eingang meiner Perl-Datei:Wie kann ich Leerzeichen getrennte STDIN Hex-Strings analysieren, die in Perl entpackt sind?

 
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 ist für char/Byte, int für die 16-Bit-Integer-Variable)

Ich wollte zunächst unpack verwenden, um sauber jeden Eingang zu trennen Zeile in Variablen, die ich brauchte. Wegen der Leerzeichenbegrenzung in der Zeichenfolge bin ich jedoch nicht sicher, wie ich damit umgehen soll (ich kann 'A' als Vorlage verwenden, aber dann kann ich auch einfach split verwenden!)

Gibt es eine elegante Möglichkeit von unpack() zu verwenden? Ich bin kein Perl-Master, aber der andere Weg ist, wie ich zuvor vorgeschlagen habe, split zu verwenden und dann jedes hex manuell in ein Byte umzuwandeln und dann Bitmanipulationen und Masken zu verwenden, um zu bekommen, was ich will. Irgendwelche anderen Vorschläge (wenn unpack nicht den Tag speichert)?

Antwort

8

jene ints sind in Big-Endian-Ordnung verwenden

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

AUSGESCHALTET beginnt, indem in den Bytes Verpackung (C*) Unter der Annahme, nach ihren Werten. Die unpack Vorlage hat folgende Teile:

  • x5 überspringt fünf Bytes
  • C2 dekodiert zwei unsigned char Werte
  • n7 decodiert sieben 16-Bit-Big-Endian-Integer ohne Vorzeichen

Ausgang:

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

Sie können es hübscher aussehen lassen, indem Sie sagen: map {hex} split :) – friedo

+2

Oder einfach nur 'map hex, split' - fast Haskell! –

+0

tatsächlich habe ich bestätigt, dass die Bytes in Little Endian sind. wierd, wie sie über ein Netzwerk gesendet werden, hätte ich gedacht, dass das in Netzwerk-Reihenfolge hätte sein sollen. Naja, die einzige Änderung muss dann "x5C2n7" auspacken um "x5C2v7" zu entpacken, oder? Und danke für die Antwort ... dieses Forum ist super – intiha

3

Wenn Sie die entpackten Daten entpacken möchten, müssen Sie sie zuerst erneut packen. Und Sie müssen die Leerzeichen entfernen, bevor Sie das tun.

Mit anderen Worten:

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

Ich eigentlich dich Diese Lösung sah aufgrund ihres sauberen Aussehens (ich verstand was der Code machte) in Kombination mit dem oben vorgeschlagenen Auspacken. und ich kann auch die $ -Zeile parsen, wenn der Java-Code eine Fehlermeldung ausgibt. – intiha

Verwandte Themen