2010-02-01 12 views
6

Ho un programma Java che sputa, in formato esadecimale separato da spazi, 16 byte di pacchetti non elaborati ricevuti in rete. Dal momento che non voglio cambiare quel codice, sto trasmettendo il risultato a uno script Perl che, in teoria, può semplicemente STDIN in variabili riconoscibili da STDIN. Il seguente è un esempio di linea di ingresso al mio file Perl:Come posso analizzare le stringhe esadecimali STDIN separate da spazio in 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 è char/byte, int per la variabile 16bit intero)

inizialmente ho voluto usare unpack per separare nettamente ogni ingresso linea in variabili che avevo bisogno. Tuttavia, a causa del limite di spazio nella stringa, non sono sicuro di come gestirlo (posso usare 'A' come modello, ma potrei anche usare lo split!)

C'è un modo elegante di usare unpack()? Non sono un master Perl, ma l'altro modo è, come ho suggerito prima, usare split e poi convertire manualmente ciascun esagono in un byte, e quindi usare manipolazioni di bit e maschere per ottenere ciò che voglio. Qualche altro suggerimento (se unpack non salva il giorno)?

risposta

8

Supponendo tali interi sono in ordine big-endian, utilizzare

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

Si inizia imballando nel byte (C*) in base ai loro valori. Il modello unpack ha le seguenti parti:

  • x5 salta cinque byte
  • C2 decodifica due unsigned char valori
  • n7 decodifica sette a 16 bit big-endian interi senza segno

uscita:

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

Puoi farlo sembrare più carino dicendo 'map {hex} split' :) – friedo

+2

O anche solo' map hex, split' - quasi Haskell! –

+0

in realtà ho confermato che i byte sono in little endian. perché, essendo inviati su una rete, avrei pensato che avrebbe dovuto essere in ordine di rete. Oh beh, l'unico cambiamento deve essere decomprimere "x5C2n7" per decomprimere "x5C2v7", giusto? E grazie per la risposta ... questo forum è fantastico – intiha

3

Se si desidera decomprimere i dati decompressi, è necessario riporli prima. E dovrai rimuovere gli spazi prima di farlo.

In altre parole,

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

Io in realtà io Se questa soluzione a causa del suo aspetto più pulito (ho capito cosa stava facendo il codice) combinato con il disimballaggio suggerito sopra. e posso anche analizzare la riga $ se il codice java sputa una stringa di errore. – intiha

Problemi correlati