2010-02-01 14 views
6

Tengo un programa Java que escupe, en formato hexadecimal separado por espacios, 16 bytes de paquetes sin procesar recibidos a través de la red. Como no quiero cambiar ese código, estoy canalizando el resultado a un script Perl que, teóricamente, puede simplemente unpack esto desde STDIN en variables reconocibles. La siguiente es una muestra de la entrada de línea a mi archivo Perl:¿Cómo puedo analizar las cadenas hexadecimales STDIN separadas por espacio 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 es para char/byte, int para la variable de 16 bits número entero)

inicialmente quería utilizar unpack para separar limpiamente cada entrada alinear las variables que necesitaba Sin embargo, debido a la delimitación de espacio en la cadena, no estoy seguro de cómo manejarlo (puedo usar 'A' como plantilla, pero entonces también podría usar split!)

¿Hay una manera elegante? de usar unpack()? No soy un maestro de Perl, pero la otra es, como sugerí antes, usar split y luego convertir manualmente cada hex a un byte, y luego usar manipulaciones de bits y máscaras para obtener lo que quiero. ¿Alguna otra sugerencia (si unpack no salva el día)?

Respuesta

8

Suponiendo que esos enteros están en orden big-endian, utilice

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

Comienza por el embalaje de los bytes (C*) de acuerdo con sus valores. La plantilla unpack tiene las siguientes partes:

  • x5 salta cinco bytes
  • C2 decodifica dos unsigned char valores
  • n7 decodifica siete de 16 bits enteros sin signo big-endian

Salida:

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

Puede hacer que se vea más bonito diciendo 'map {hex} split' :) – friedo

+2

O incluso simplemente' map hex, split' - ¡casi Haskell! –

+0

en realidad confirmó que los bytes están en little endian. Por extraño que sea que se envíen a través de una red, pensé que debería haber estado en el orden de la red. Oh, bueno, el único cambio necesita ser descomprimir "x5C2n7" para descomprimir "x5C2v7", ¿verdad? Y gracias por la respuesta ... este foro es impresionante – intiha

3

Si desea utilizar el desempaquetado de los datos desempacados, primero deberá volver a empacarlos. Y deberá eliminar los espacios antes de hacer eso.

En otras palabras,

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

En realidad, u Se esta solución debido a su aspecto más limpio (entendí lo que estaba haciendo el código) combinado con el desembalaje sugerido anteriormente. y también puedo analizar la $ línea si el código java escupe una cadena de error. – intiha

Cuestiones relacionadas