Chris Huang-Leaver
Chris Huang-Leaver

Reputation: 6089

How can I convert hex strings into numbers in Perl?

I recently wrote a script which parsed a text representation of a single binary byte month field.

(Don't ask :-{ )

After fiddling with sprintf for a while I gave up and did this;

our %months = qw / x01 1 
       x02 2
       x03 3 
       x04 4 
       x05 5 
       x06 6 
       x07 7 
       x08 8 
       x09 9 
       x0a 10 
       x0b 11 
       x0c 12 /;
...
my $month = $months{$text};

Which I get away with, because I'm only using 12 numbers, but is there a better way of doing this?

Upvotes: 30

Views: 69551

Answers (4)

WhiteMist
WhiteMist

Reputation: 915

Here's another way that may be more practical for directly converting the hexadecimals contained in a string.

This make use of the /e (e for eval) regular expression modifier on s///.

Starting from this string:

$hello_world = "\\x48\\x65\\x6c\\x6c\\x6f\\x20\\x57\\x6f\\x72\\x6c\\x64";

Hexadecimals to characters:

print $hello_world =~ s/\\x([0-9a-fA-F]{2})/chr hex $1/gre;

Hexadecimals to decimal numbers:

print $hello_world =~ s/\\x([0-9a-fA-F]{2})/hex $1/gre;

Drop the /r modifier to substitute the string in-place.

One day, I used a Python script that did stuff with a binary file and I was stuck with a bytes literal (b'\x09\xff...') containing only hexadecimal digits.

I managed to get back my bytes with a one-liner that was a variant of the above.

Upvotes: 0

Nathan Fellman
Nathan Fellman

Reputation: 127608

If you have

$hex_string = "0x10";

you can use:

$hex_val = hex($hex_string);

And you'll get: $hex_val == 16

hex doesn't require the "0x" at the beginning of the string. If it's missing it will still translate a hex string to a number.

You can also use oct to translate binary, octal or hex strings to numbers based on the prefix:

  • 0b - binary
  • 0 - octal
  • 0x - hex

Upvotes: 43

Sinan Ünür
Sinan Ünür

Reputation: 118166

See hex and/or oct.

#!/usr/bin/perl

use strict;
use warnings;

my @months = map hex, qw/x01 x02 x03 x04 x05 x06 x07 x08 x09 x0a x0b x0c/;
print "$_\n" for @months;

Upvotes: 9

user80168
user80168

Reputation:

If I understand correctly you have 1 byte per month - not string "0x10", but rather byte with 10 in it.

In this way, you should use unpack:

my $in = "\x0a";
print length($in), "\n";
my ($out) = unpack("c", $in);
print length($out), "\n", $out, "\n"

output:

1
2
10

If the input are 3 characters, like "x05", then changing is also quite simple:

my $in = "x0a";
my $out = hex($in);

Upvotes: 3

Related Questions