2010-07-16 14 views
5

Sono abbastanza nuovo per lo sviluppo di Perl, e mi piacerebbe svolgere un compito seguente:Perl: analizzare la stringa esadecimale codificata in array con regex

Il mio script riceve stringa esadecimale-codificato come da riga di comando param . Quindi devo decodificare questa stringa e scriverla in un file di output come un array C++ con inizializzazione dai dati forniti. Per esempio:

perl myscript.pl DEADBABEDEADBEEF e l'uscita qualcosa come

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

Qual è il modo giusto per fare questo con il Perl regex? Certo, potrei eseguirlo in loop con sottostringhe, ma credo che ci dovrebbe essere un modo più elegante.

MODIFICA: la stringa di input è di lunghezza fissa.

+1

Che dire di Split/Map? A meno che tu non sia sicuro che la tua stringa di input sia di lunghezza fissa, dubito che regexp sarebbe una buona scelta. –

+0

Sì, in questo caso sono sicuro che la mia stringa di input sarà di lunghezza fissa. Aggiornerò la domanda – Haspemulator

risposta

6

Prova questo:

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

Come funziona:

In primo luogo, $hex =~ /(..)/g in contesto lista cattura tutte le sottostringhe 2 caratteri (i /g mezzi bandiera partita globale). Quindi lo map() prende l'elenco e lo trasforma in un altro, usando l'espressione "0x$_" per ogni elemento del primo elenco ($_ qui c'è un alias per l'elemento).

Vedere anche perldoc -f map.

+0

Grazie, il tuo script funziona. Ma potresti spiegarmi i dettagli? Cosa è successo lì, e qual è il "," (virgola) tra l'operazione? Come ho detto, sono abbastanza nuovo per Perl. :) – Haspemulator

+0

@Haspemulator: è un ordine abbastanza alto. Prova 'perldoc -f map' per ottenere la documentazione per la funzione mappa, e' perldoc perlre' per ottenere la documentazione per le espressioni regolari. –

+0

@Kinopiko, grazie per il commento, ora è più chiaro. – Haspemulator

5

ne dite di questo:

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

Grazie, la tua risposta è corretta. Ma anche la seconda risposta è corretta. Non sono sicuro per chi dovrei votare. :) E ho una domanda sul tuo codice: perché in istruzione '$ input = ~ s/([0-9A-F] {2}) //' hai lasciato il secondo argomento di s /// vuoto? Cosa significa questo in questo contesto? – Haspemulator

+0

Elimina solo i primi due caratteri ogni volta. Metti un 'print $ input' nel ciclo e vedrai come funziona. –

+0

@Kinopiko, ok, ce l'ho. Grazie. – Haspemulator

4

Che ne dici di decomprimere?

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

Correzione - avresti bisogno di una mappa per precedere ogni elemento che spacchettare torna con un "0x"

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