I'm trying to write a script to find hex strings in a text file and convert them to their reverse byte order. The trouble I'm having is that some of the hex strings are 16-bit and some are 64 bits. I've used Perl's pack
to pack and unpack the 16-bit hex numbers and that works fine, but the 64-bit does not.
print unpack("H*", (pack('I!', 0x20202032))). "\n"; #This works, gives 32202020
#This does not
print unpack("H*", (pack('I!', 0x4f423230313430343239303030636334))). "\n";
I've tried the second with the q
and Q
(where I get ffffffffffffffff
). Am I approaching this all wrong?
As bit of background, I've got a multi-gigabyte pipe-delimited text file that has hex strings in reverse byte order as explained above. Also, the columns of the file are not standard; sometimes the hex strings appear in one column, and sometimes in another. I need to convert the hex strings to their reverse byte order.
Always use warnings;
. If you do, you'll get the following message:
Integer overflow in hexadecimal number at scratch.pl line 8.
Hexadecimal number > 0xffffffff non-portable at scratch.pl line 8.
These can be resolved by use bigint;
and by changing your second number declaration to hex('0x4f423230313430343239303030636334')
.
However, that number is still too large for pack 'I'
to be able to handle.
Perhaps this can be done using simple string manipulation:
use strict;
use warnings;
my @nums = qw(
0x20202032
0x4f423230313430343239303030636334
);
for (@nums) {
my $rev = join '', reverse m/([[:xdigit:]]{2})/g;
print "$_ -> 0x$rev\n"
}
__END__
Outputs:
0x20202032 -> 0x32202020
0x4f423230313430343239303030636334 -> 0x3463633030303932343034313032424f
Or to handle digits of non-even length:
my $rev = $_;
$rev =~ s{0x\K([[:xdigit:]]*)}{
my $hex = $1;
$hex = "0$hex" if length($hex) % 2;
join '', reverse $hex =~ m/(..)/g;
}e;
print "$_ -> $rev\n"