2010-07-16 18 views
5

Je suis tout à fait nouveau pour le développement Perl, et je voudrais effectuer une tâche suivante:Perl: analyser la chaîne encodée à six pans en tableau avec regex

Mon script reçoit chaîne hexadécimale codée comme ligne de commande param . Ensuite, je dois décoder cette chaîne et l'écrire dans un fichier de sortie comme un tableau C++ avec initialisation à partir des données fournies. Par exemple:

perl myscript.pl DEADBABEDEADBEEF et quelque chose de sortie comme

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

Quelle est la bonne façon de le faire avec Perl regex? Bien sûr, je pourrais l'effectuer en boucle avec des sous-chaînes, mais je crois qu'il devrait y avoir une manière plus élégante.

EDIT: la chaîne d'entrée est de longueur fixe.

+1

Qu'en est-il de Split/Carte? Sauf si vous êtes sûr que votre chaîne d'entrée est de longueur fixe, je doute que regexp serait un bon choix. –

+0

Oui, dans ce cas, je suis sûr que ma chaîne d'entrée sera de longueur fixe. Je vais mettre à jour la question. – Haspemulator

Répondre

6

Essayez ceci:

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

Comment ça marche:

D'abord, $hex =~ /(..)/g dans un contexte de liste capture toutes les sous-2 caractères (les /g moyens de drapeau match global). Puis map() prend la liste et la transforme en une autre, en utilisant l'expression "0x$_" pour chaque élément de la première liste ($_ voici un alias pour l'élément).

Voir aussi perldoc -f map.

+0

Merci, votre script fonctionne. Mais pourriez-vous m'expliquer les détails? Que se passe-t-il là, et quel est le ',' (virgule) entre l'opération? Comme je l'ai dit, je suis assez nouveau pour Perl. :) – Haspemulator

+0

@Haspemulator: C'est assez difficile. Essayez 'perldoc -f map' pour obtenir la documentation de la fonction map, et' perldoc perlre' pour obtenir la documentation des expressions régulières. –

+0

@Kinopiko, merci pour le commentaire, il est plus clair maintenant. – Haspemulator

5

Que diriez-vous ceci:

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

Merci, votre réponse est correcte. Mais la deuxième réponse est correcte, aussi. Je ne suis pas sûr pour qui devrais-je voter. :) Et j'ai une question sur votre code: pourquoi dans l'instruction '$ input = ~ s/([0-9A-F] {2}) //' vous avez laissé le second argument de s /// vide? Qu'est-ce que cela signifie dans ce contexte? – Haspemulator

+0

Il supprime simplement les deux premiers caractères à chaque fois. Mettez un 'print $ input' dans la boucle et vous verrez comment cela fonctionne. –

+0

@Kinopiko, ok, je l'ai. Je vous remercie. – Haspemulator

4

Que diriez-vous de déballer?

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

Correction - vous auriez besoin d'une carte de préfixer chaque élément qui déballer revient avec un "0x"

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