LloydRice has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to do something that is probably stupidly simple, but it's just not working. I have a string with some decimal digits and some uppercase A..F. The string does NOT begin with "0X". I am simply trying to get the hex value into a variable. I've tried various prefixes, sprintf with various formats, pack, unpack, and a few more things. It's just not working ???

Replies are listed 'Best First'.
Re: hex numbers
by haukex (Bishop) on Jan 14, 2021 at 13:32 UTC
    I am simply trying to get the hex value into a variable.

    If by that you mean converting something like the string "FE" into the number 254, then what you are looking for is hex.

    Update: And if that's not what you're looking for, please show an SSCCE, in particular please show the contents of the variable you're trying to convert using Data::Dump or Data::Dumper with $Data::Dumper::Useqq=1;.

Re: hex numbers
by davido (Cardinal) on Jan 14, 2021 at 17:11 UTC

    The 0xNNNN notation is a source-code feature. It is parsed at compile-time. So this works:

    my $n = 0xDEADBEEF; print "$n\n"; # Output: # 3735928559

    And this works but you shouldn't use it:

    # This works but is NOT recommended, and can be unsafe. my $n = eval "0xDEADBEEF"; print "$\n"; # Output: # 3735928559

    That second example works because even though we've created a string of characters, "0xDEADBEEF", the eval statement evaluates that string as source code, so it gets parsed and compiled when the statement is executed at runtime.

    This doesn't work:

    my $n = "0xDEADBEEF"; print "$n\n"; # Output: # 0xDEADBEEF

    It didn't work because the string was taken as plain old characters. Since you want to take a string of characters and interpret them as a hex digits you should use the hex function:

    This is the version you should use:

    my $string = "DEADBEEF"; my $n = hex($string); print "$n\n"; # Output: # 3735928559


      And this works but you shouldn't use it:
      # This works but is NOT recommended, and can be unsafe. my $n = eval "0xDEADBEEF"; print "$\n"; # Output: # 3735928559

      It is not unsafe. "0xDEADBEEF" is a string constant. It is just as if 0xDEADBEEF had been put into the source code at the first place, with the difference that the literal is evaluated at compile time, whereas eval "0xDEADBEEF"; is evaluated at run time. Neither of them is safer than the other.

      String eval is not unsafe per se - but it is unsafe if applied upon strings of dubious provenience. Every piece of perl code (which is a bunch of strings) is eval-ed by the perl binary.

      perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'

        I'm certainly aware that many modules even do this:

        our $VERSION = "1.2.3_001"; $VERSION = eval $VERSION;

        As documented in perlmodstyle, I think. The specific code I used in the example isn't unsafe. But the evaluation of a string can be unsafe if the string's source isn't well controlled. And if the original poster were able to hard code hex, he could do so using 0x literals. Since he's not using 0x literals, I assume that's because the hex strings are coming from somewhere external. And at that point the caveats about evaluating strings apply.

        But you're correct. What I posted isn't inherently unsafe. The practice is inherently easy to make unsafe, though.


        It is not unsafe.

        davido didn't say that: "This works but is NOT recommended, and can be unsafe", and at least to me it's obvious that this refers to what you said:

        it can be unsafe if used upon strings of dubious provenience

        If one is doing eval, one is usually using it on strings based on user input or dynamically generated strings, otherwise one wouldn't have to eval in the first place!

        Stringy eval is one of those "only do this if you really know what you are doing" type of things, so while your clarification certainly isn't wrong, I also think warning against it is absolutely the right thing.

Re: hex numbers
by AnomalousMonk (Bishop) on Jan 14, 2021 at 17:37 UTC

    Also note that oct mimics hex for raw octal numeric strings and for all other common, non-decimal-base numeric strings given the appropriate prefix.

    Win8 Strawberry (32) Thu 01/14/2021 12:26:05 C:\@Work\Perl\monks >perl -Mstrict -Mwarnings for my $s (qw(376 37_6 0376 0_376 0xfe 0xf_e 0b11111110 0b1111_1110)) +{ print "'$s' "; die 'Ooops...' unless oct $s == 254; } print "\n"; print "all ok \n"; ^Z '376' '37_6' '0376' '0_376' '0xfe' '0xf_e' '0b11111110' '0b1111_1110' all ok

    Give a man a fish:  <%-{-{-{-<

Re: hex numbers
by ikegami (Pope) on Jan 15, 2021 at 02:44 UTC
    To convert from the hex representation to a number, simply use hex.
    my $num = hex($hex);
Re: hex numbers
by LloydRice (Beadle) on Jan 14, 2021 at 13:27 UTC
    If I put a "0X" in front and then try to get the value, it just looks like a possibly decimal number with some funny stuff in front.