2010-02-01 6 views
6

J'ai un programme Java qui crache, en format hexadécimal séparé par un espace, 16 octets de paquets bruts reçus sur le réseau. Puisque je ne veux pas changer ce code, je passe le résultat à un script Perl qui, théoriquement, peut simplement le transformer en en variables reconnaissables. Ce qui suit est un échantillon de l'entrée de ligne de mon fichier Perl:Comment puis-je analyser les chaînes hexadécimales STDIN séparées de l'espace décompressées en 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 est pour char/octet, int pour la variable de nombre entier de 16 bits)

je voudrais d'abord d'utiliser unpack pour séparer proprement chaque entrée ligne dans les variables dont j'avais besoin. Cependant, en raison de la délimitation de l'espace dans la chaîne, je ne suis pas sûr de la gérer (je peux utiliser 'A' comme modèle, mais je pourrais aussi bien utiliser split!)

Y at-il un moyen élégant? d'utiliser unpack()? Je ne suis pas un maître Perl, mais l'autre façon est, comme je l'ai suggéré précédemment, d'utiliser split puis de convertir manuellement chaque hexagone en octet, puis d'utiliser des manipulations de bits et des masques pour obtenir ce que je veux. D'autres suggestions (si unpack ne sauve pas la journée)?

Répondre

8

Si l'on suppose ces ints sont dans l'ordre big-endian, utilisez

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

Il commence par l'emballage dans les octets (C*) en fonction de leurs valeurs. Le modèle unpack comprend les éléments suivants:

  • x5 saute cinq octets
  • C2 décode deux unsigned char valeurs
  • n7 décode les sept 16 bits gros-boutiste entiers non signés

sortie:

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

Vous pouvez le rendre plus joli en disant 'map {hex} split' :) – friedo

+2

Ou même juste' map hex, split' - presque Haskell! –

+0

effectivement j'ai confirmé que les octets sont en petit boutiste. wierd, comme ils sont envoyés sur un réseau, j'aurais pensé que cela aurait dû être dans l'ordre du réseau. Eh bien, le seul changement doit alors être déballer "x5C2n7" pour déballer "x5C2v7", non? Et merci pour la réponse ... ce forum est génial – intiha

3

Si vous souhaitez utiliser le déballage sur des données décompressées, vous devez d'abord les emballer à nouveau. Et vous devrez supprimer les espaces avant de faire cela.

En d'autres termes,

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

En fait, je vous Cette solution est due à son aspect plus propre (j'ai compris ce que le code faisait) combiné avec le déballage suggéré ci-dessus. et je peux aussi analyser la ligne $ si le code java crache une chaîne d'erreur. – intiha