2010-07-16 6 views
5

estoy bastante nuevo en el desarrollo de Perl, y me gustaría llevar a cabo una tarea siguiente:Perl: analizar la cadena hexadecimal codificado en matriz con expresiones regulares

Mi script recibe cadena hexadecimal-codificado como parámetro de línea de comandos . Luego debo decodificar esta cadena y escribirla en el archivo de salida como una matriz C++ con la inicialización de los datos proporcionados. Por ejemplo:

perl myscript.pl DEADBABEDEADBEEF y la salida como algo

const boost::array<char, 8> MyArray = { 0xDE, 0xAD, 0xBA, 0xBE, 0xDE, 0xAD, 0xBE, 0xEF };

¿Cuál es la forma correcta de hacer esto con expresiones regulares de Perl? Por supuesto, podría hacerlo en bucle con subcadenas, pero creo que debería haber una manera más elegante.

EDITAR: la cadena de entrada es de longitud fija.

+1

Qué sobre Split/Mapa? A menos que esté seguro de que su cadena de entrada es de longitud fija, dudo que la expresión regular sea una buena opción. –

+0

Sí, en este caso estoy seguro de que mi cadena de entrada será de longitud fija. Actualizaré la pregunta. – Haspemulator

Respuesta

6

Prueba esto:

my $hex = "DEADBABEDEADBEEF"; 
my @a = map "0x$_", $hex =~ /(..)/g; 

Cómo funciona:

En primer lugar, $hex =~ /(..)/g en el contexto de lista capta todas las subcadenas de 2 caracteres (los /g medios bandera partido global). A continuación, map() toma la lista y la transforma en otra, utilizando la expresión "0x$_" para cada elemento de la primera lista ($_ aquí hay un alias para el elemento).

Véase también perldoc -f map.

+0

Gracias, tu script funciona. ¿Pero podrías explicarme los detalles? ¿Qué sucede allí, y qué es el ',' (coma) entre la operación? Como dije, soy bastante nuevo para Perl. :) – Haspemulator

+0

@Haspemulator: Es una tarea bastante difícil. Pruebe 'perldoc -f map' para obtener documentación para la función de mapa, y' perldoc perlre' para obtener documentación para expresiones regulares. –

+0

@Kinopiko, gracias por su comentario, ahora está más claro. – Haspemulator

5

¿Qué tal esto:

my $input = $ARGV[0]; 
die "Fouled up input" unless $input =~ /^(?:[0-9A-F]{2})+$/i; 
my $bytes = length ($input)/2; 
print "const boost::array<char, $bytes> MyArray = {"; 
while ($input =~ s/([0-9A-F]{2})//i) { 
    # print $input # to see how this works, see comment. 
    print "0x$1, "; 
} 
print "};\n"; 
+0

Gracias, su respuesta es correcta. Pero la segunda respuesta es correcta también. No estoy seguro de a quién debería votar. :) Y tengo una pregunta acerca de tu código: ¿por qué en la declaración '$ input = ~ s/([0-9A-F] {2}) //' dejaste el segundo argumento de s /// vacío? ¿Qué significa esto en este contexto? – Haspemulator

+0

Simplemente borra los dos primeros caracteres cada vez. Ponga 'print $ input' en el bucle y verá cómo funciona. –

+0

@Kinopiko, vale, ya lo tengo. Gracias. – Haspemulator

4

¿Qué tal unpack?

print join ",", unpack("(A2)*", "DEADBABEDEADBEEF"); 

corrección - que había necesidad de un mapa para prefijar cada elemento que desempaquetar vuelve con un "0 x"

print join ",", map { '0x' . $_ } unpack("(A2)*", "DEADBABEDEADBEEF"); 
Cuestiones relacionadas