[Chicago-talk] Parsing a Hex file

Andrew Rodland arodland at comcast.net
Sat Jan 20 03:40:26 PST 2007


On Friday 19 January 2007 3:41 pm, Pete Krawczyk wrote:
> unpack doesn't do the looping you want, as far as I'm aware.  However, I'm
> pretty sure the following loop will do what you're looking for:
>
>     while (length($file_contents)) {
>         my ($field_num, $value) = unpack("SC/A", $file_contents);
> 	# something with $field_num and $value
>         my $len = length($value);
>         $file_contents = substr($file_contents,$len+3);
>     }
>
> Of course, I'm using "C" to mean "8-bit integer", but I don't know any
> more elegant way to do that.

Unpack does do the looping, although you still have to do a little processing 
on it afterwards until Perl6 shows up

# Jay's example input field, repeated 3x
my $input = "\x94\x00\x0b\x4a\x41\x59\x27\x53\x20\x46\x4f\x4f\x44\x53" x 3;
my @data = unpack("(SC/A)*", $input); # produce a key/value list
for (my $i = 0 ; $i < $#data ; $i += 2) { # and print out by pairs
    print "$data[$i]:\t$data[$i+1]\n";
}
print ".\n";

=== will output ===

148:    JAY'S FOODS
148:    JAY'S FOODS
148:    JAY'S FOODS
.

though if you weren't concerned of the order that the fields came in, there 
_is_ one place where perl expects a list of alternating keys and values, and 
that's in the assignment of a hash from a list.

%hash = unpack("SC/A", $etc);

will work if you don't care about order and can't have any dupes. You could 
also use a for loop or a thoroughly evil map to turn (148, "JAY'S FOODS", 
148, "JAY'S FOODS", 148, "JAY'S FOODS") into ([148, "JAY'S FOODS"], 
[148, "JAY'S FOODS"], [148, "JAY'S FOODS]) which is slightly more convenient.

Hope I've put some good ideas into your head :)

Andrew


More information about the Chicago-talk mailing list