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

I'm unfamiliar with Perl's unpack routine, so I was wondering how I would convert a hex value to an Octet String (i.e.)
0xb400189 => 89.1.40.B
Any help would be greatly appreciated :)

Replies are listed 'Best First'.
Re: Hex to Octet
by sgifford (Prior) on Sep 09, 2003 at 18:09 UTC
    I'm not sure exactly what conversion you want, but here's the most straightforward numerical way I came up with. It gives octets in big-endian order, which is backwards from what your example does.
    #!/usr/bin/perl my $hexstr = "0xb400189"; # Convert to a number in machine-byte order my $num = hex $hexstr; # Convert to a number in big-endian order my $be_num = pack("N",$num); # Extract the 4 bytes my($a,$b,$c,$d) = unpack("C4",$be_num); # And print! printf "%x.%x.%x.%x\n",$a,$b,$c,$d;
    That can be simplified to a one-liner:
    printf "%x.%x.%x.%x\n", unpack("C4",pack("N",hex $hexstr));
      Thank you,
      That is what I was looking for, now if I wanted to do the reverse should I substitute unpack for pack?

      Thank again

        I built upon sgifford's code.

        #!/usr/bin/perl my $hex = "0xb400189"; # the 0x is optional since we call hex later my $octet = hex2octet($hex); print $octet, "\n"; $hex = octet2hex($octet); print $hex, "\n"; sub hex2octet { my $hex = shift; my @octet = unpack("C4", pack("N", hex $hex)); return sprintf "%x.%x.%x.%x", reverse @octet; } sub octet2hex { my $octet = shift; my @octet = map { hex } split /\./, $octet; my $hex = unpack("N", pack("C4", reverse @octet)); return sprintf "%x", $hex; }

Re: Hex to Octet
by hardburn (Abbot) on Sep 09, 2003 at 18:27 UTC
    perl -le '$_ = pop; s/\A..//; $_ = "0$_" if length() % 2; print join ".", reverse unpack("A2" x (length() / 2), $_);'

    Put the hex value you want to convert as its single argument.

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    Note: All code is untested, unless otherwise stated

Re: Hex to Octet
by blue_cowdawg (Monsignor) on Sep 09, 2003 at 19:13 UTC

    Here's a thought:

    $hex="abcdef0123"; $hex=~s/([0-9a-fA-F]{2})/$1=/g; @digits=split(/=/,$hex); $octets=join(".",reverse @digits); printf "%s\n%s\n",$hex,$octets;
    when the code is run it yeilds:
    perl octet.pl ab=cd=ef=01=23= 23.01.ef.cd.ab


    Peter L. Berghold -- Unix Professional
    Peter at Berghold dot Net
       Dog trainer, dog agility exhibitor, brewer of fine Belgian style ales. Happiness is a warm, tired, contented dog curled up at your side and a good Belgian ale in your chalice.
Re: Hex to Octet
by flounder99 (Friar) on Sep 09, 2003 at 19:55 UTC
    $hex= 0xb400189; print join ".", map {scalar reverse}(reverse sprintf "%x", $hex) =~/(. +.?)/g; __OUTPUT__ 89.01.40.b

    --

    flounder

Re: Hex to Octet
by dmitri (Priest) on Sep 09, 2003 at 18:04 UTC
    Why not use sprintf:
    perl -e 'print sprintf("%o", 0xb400189)'

    Update: I should read the questions more carefully before responding.

      The poster didn't ask for 'hex to octal', but wanted an "octet string" of a given format.

      Once upon a time, a 'byte' wasn't necessarily eight bits It could be 4. ASCII was defined when it was often 7 bits per byte. The word 'octet' is used to refer to an eight bit entity, regardless of the byte size, word size, bus size, stop or parity scheme, or other implementation details.

      The poster could/should look at the unpack function (perldoc -f unpack) for some ideas. It can be done with a simple string manipulation but it's more flexible if you unpack to four octets, then format it again (with sprintf "%x" or any other method).

      --
      [ e d @ h a l l e y . c c ]