Mike Manning
Mike Manning

Reputation: 25

How can I convert a hex string in perl to ascii?

I have an old legacy system that is pulling postgres bytea data from a database (can't change the code as it's compiled). How do I go about converting bytea data that is in this format to an ascii string?

Here is a sample of the data:

my($value) = "\x46726f6d3a20224d";

I found this example online to decode a hex string, but the input has to start with 0x, not \x. If I change the test string from \x to 0x then this example works however the \x is treating the next HEX 46 as a capital F as it's doing the regex match, then the rest is failing to decode.

Here is the regex I had found that works with a string starting with 0x but not \x, Is it possible to decode this type of hex string somehow?

$value =~ s/0x(([0-9a-f][0-9a-f])+)/pack('H*', $1)/ie;
print $value, "\n";

Correct output when you use 0x on the input string:

From: "M

Incorrect output (not decoded) when using \x on the input string:

F726f6d3a20224d

Cheers, Mike

Upvotes: 0

Views: 444

Answers (1)

ikegami
ikegami

Reputation: 385565

Assuming you actually have the string

\x46726f6d3a20224d

as produced by

my $value = "\\x46726f6d3a20224d";

Then all you just need to replace the 0 with \\.

$value =~ s/\\x(([0-9a-f][0-9a-f])+)/pack('H*', $1)/ie;

Better (less repetition and it avoids slowdowns related to ß):

$value =~ s/\\x((?:[0-9a-fA-F]{2})+)/ pack( 'H*', $1 ) /e;

If you expect this to be the whole string, then I'd use

$value = pack( 'H*', $value =~ s/^\\x//r );

The following is faster, but loses some validation:

$value = pack( 'H*', substr( $value, 2 ) );

Upvotes: 2

Related Questions