[comp.unix.shell] awk, how to convert hex to decimal

gregs@well.sf.ca.us (Greg Strockbine) (02/05/91)

How do I convert a hex number (or is it string) into decimal?

Here is the problem, I take a snap shot of a hex dump from a debugger,
use sed to extract the line I'm interested in, then pass it to awk.
So I've got this field 930A and use the awk substr to break this into
2 fields, a=93 and b=0A.  So that's 2 hex numbers represented as strings
but I want to print the 93 out as a decimal number and I want to use the
0A as an index into an array of messages so I can print out a corresponding
message.
Can I use an associative array for the messages and say something like:
usr_msg = messages[0A]?

How do I convert the 93 to decimal?

Thanks in advance.

]) (02/06/91)

Here's the only semi-decent solution to this that *I* have found,
which isn't to say there's not some way to get sprintf to handle it.

# awk script to convert hex to decimal on output (an opcode in
# chars 1 and 2 of $1) and display the indexed message tagged
# by chars 2 and 3.
#
# Much much better idea to do this with C!
BEGIN {
        # Set up the conversion-array Dec[]
        for ( i = 0; i <= 9; i++ )
                Dec[i] = i
        Dec["A"] = 10
        Dec["B"] = 11
        Dec["C"] = 12
        Dec["D"] = 13
        Dec["E"] = 14
        Dec["F"] = 15
	Dec["a"] = 10
	Dec["b"] = 11
	Dec["c"] = 12
	Dec["d"] = 13
	Dec["e"] = 14
	Dec["f"] = 15

        # Message array
        Msg["0A"] = "This is message OA"
	Msg["0a"] = Msg["0A"]
        }

        {
        a = substr($1, 1, 1)
        b = substr($1, 2, 1)
        opcode = (16 * Dec[a]) + Dec[b]

        msgid = substr($1, 3, 2)
	# We won't use it, but what the heck -- convert msgid to decimal
	c = substr($1, 3, 1)
	d = substr($1, 4, 1)
	msgcode = (16 * Dec[c]) + Dec[d]

        printf("op(%d) id(%s): %s\n", opcode, msgid, Msg[msgid])
        }


By the way, a general-case conversion walks along a string, char by
char (as mentioned in another article).  Assuming that you want to
convert the character-string hex number in $1 to decimal, and the
Dec[] array has been defined as above...

	{
	a=0
	for ( i = 1; i <= length($1); i++ )
		{
		c = substr($1, i, 1)
		a = (16 * a) + Dec[c]
		}
	}

and the variable 'a' has the decimal value of (hex) $1.  The key to this
is that each successive character requires the sum of all the previously
evaluated characters to be multiplied by 16 (left-shift one char or four
bits).  For a four-char hex, char 1 is multiplied by 16 three times, char
2 twice, char 3 once, and char 4 not at all.

...Kris
-- 
Kristopher Stephens, | (408-746-6047) | krs@uts.amdahl.com | KC6DFS
Amdahl Corporation   |                |                    |
     [The opinions expressed above are mine, solely, and do not    ]
     [necessarily reflect the opinions or policies of Amdahl Corp. ]

art@pilikia.pegasus.com (Art Neilson) (02/06/91)

In article <23000@well.sf.ca.us> gregs@well.sf.ca.us (Greg Strockbine) writes:
>How do I convert a hex number (or is it string) into decimal in awk ?

Here's my stab at it!

function htoi(s) {
	split("A\tB\tC\tD\tE\tF", u)
	len = split("a\tb\tc\td\te\tf", l)
	for (i = 1; i <= len; i++)
		uhex[u[i]] = lhex[l[i]] = 9 + i
	for (i = 1; i <= length(s); i++) {
		c = substr(s, i, 1)
		if (c ~ /[0-9]/)
			v = c + 0
		if (c ~ /[A-F]/)
			v = uhex[c]
		if (c ~ /[a-f]/)
			v = lhex[c]
		n = 16 * n + v
	}
	return n
}
-- 
Arthur W. Neilson III		| INET: art@pilikia.pegasus.com
Bank of Hawaii Tech Support	| UUCP: uunet!ucsd!nosc!pegasus!pilikia!art

darcy@druid.uucp (D'Arcy J.M. Cain) (02/08/91)

In article <23000@well.sf.ca.us> gregs@well.sf.ca.us (Greg Strockbine) writes:
>How do I convert a hex number (or is it string) into decimal?

The following command will convert a hex number such as 93 (stored as
HEXNUM) into decimal:

    DECNUM=`echo "16 i $HEXNUM p" | dc`

However on my system (Esix Rel D SysV3.2) at least it won't work on the
output from hd(1) since it barfs on lower case letters.  Is this the
normal way for dc to work?  I guess the following line will be a general
purpose converter but I'm sure there must be a better way.

  HEXNUM=`echo $HEXNUM | tr [a-z] [A-Z]`
  DECNUM=`echo "16 i $HEXNUM p" | dc`

-- 
D'Arcy J.M. Cain (darcy@druid)     |
D'Arcy Cain Consulting             |   There's no government
West Hill, Ontario, Canada         |   like no government!
+1 416 281 6094                    |