Search code examples
bashhexbytehexdump

How to work with large Hexadecimal values without converting to a string?


In bash I am SNMP'ing my printer to get some information, the snmp response looks like this:

080118000001FFFB000000020000FFFFFFFD0007FFFEFFFAFFFE0011FFFEFFD507FB000FFF8E001C0006FFF9FFF2FFFE000100040005000600030002000100000007FFFDFFFEFFFE00020008FFFFFFFF0000000100000000FFFC0004FFFDFFFE00010002

Based on the development documentation it states the first four byte-long elements in the header are to be 6th byte which is 18 can be interpreted in HEX mode which is pretty straight forward. For example, the number of logged on users which in the 6th byte is 18 HEX do it is 24 in decimal. The rest of the data is defined in two byte increments containing the real and imaginary values and should be interpreted according to 2’s complement over the entire two bytes or 4 nibbles.

When converting these to 10 based numbers, do I have to convert it to a string and perform sub string functions or is there a function in bash that will allow me to convert it based on the byte value. Meaning I just want to convert the 17th byte?


Solution

  • Using bash

    $ s='0801180000...'
    $ b=0x${s:4:2}
    $ echo $((b))
    24
    

    To select the substring 18 from the string s, we use bash's substring expansion: ${s:4:2}. This is then combined with arithmetic expansion, $((...)) to convert the hexadecimal number to decimal.

    Using awk

    $ echo '0801180000...' | awk '{print strtonum("0x" substr($1,5,2));}'
    24
    

    How it works

    • substr($1,5,2)

      This returns a 2-character substring from starting with the 5th character. For your input, this returns the 18.

      Because awk uses and index origin of 1, rather than 0, the substring 18 starts at position 1 in awk.

    • "0x" substr($1,5,2)

      Since, by convention, hexadecimal strings start with 0x, this add the string 0x to the substring we asked for to produce the string 0x18

    • strtonum("0x" substr($1,5,2))

      This converts the string 0x18 from hexadecimal to decimal.