2

I am attempting to compare two strings containing hexadecimal numbers in a dash test, one which has leading zeros and one which doesn't:

hex_string_1: 0x02a0000b
hex_string_2: 0x2a0000b

Trying if [ ${hex_string_1} -eq ${hex_string_2} ] ; then ... (or vice versa, the leading zeros don't seem to matter) gives me this error:

[: Illegal number: 0x02a0000b

Is there a simple way to compare these as numbers, rather than e.g. using sed to reformat the strings?

Since I'm using dash and not bash,[[ isn't an option.

UPDATE: This worked (thanks ott!):

[ $(printf "%d" ${hex_string_1}) -eq $(printf "%d" ${hex_string_2}) ]
  • Why not just do a string comparison instead? Do you really need an arithmetic comparison if you're just testing equality? – terdon Sep 26 '15 at 19:18
  • -eq is only allowed for for what the shell accepts as an integer. Convert the values with `iv1=$(printf "%d\n" 0x...), then compare. – ott-- Sep 26 '15 at 20:22
  • Please do not update your question with answer, that is information that doesn't belong there and not the way this site works. You should either ask ott to make her comment into an answer, or make it yourself into answer and then accept that. That way it is clear this issue is solved, because now it is not unless your not distracted by content like UPDATE and thanks typical for low quality posts – Anthon Sep 28 '15 at 7:18
3

POSIXly:

[ "$((hex_string_1))" -eq "$((hex_string_2))" ]

With older versions of dash, you needed:

[ "$(($hex_string_1))" -eq "$(($hex_string_2))" ]

POSIXly, About:

[ "$hex_string_1" -eq "$hex_string_2" ]

The POSIX specification for the [ aka test utility says operands have to be integers, without specifying which forms of integers (decimal, octal, hexadecimal...) are to be supported, but that's actually covered in point 6 at the Utility Argument Syntax which states what the default would be when not specified:

 6. Unless otherwise specified, whenever an operand or option-argument is, or contains, a numeric value:

  • The number is interpreted as a decimal integer.
  • Numerals in the range 0 to 2147483647 are syntactically recognized as numeric values.
  • When the utility description states that it accepts negative numbers as operands or option-arguments, numerals in the range -2147483647 to 2147483647 are syntactically recognized as numeric values.
  • Ranges greater than those listed here are allowed.

In practice, [ 0x10 -eq 16 ] only works with posh ([ 0x1 -eq 0x01] works in AT&T ksh (but only because they're treated as 0, [ 0x2 -eq 0x123 ] would return true as well), and except for posh (where's that a bug), all [ implementations return false on [ 010 -eq 8 ] (as in 010 is treated as decimal, not octal)).

In ksh93, while you can't do [ 0x10 -eq 16 ], you can do [ +0x10 -eq 16 ] (also with posh). In both AT&T ksh and pdksh derivatives (including posh), you can also do [ '16#10' -eq 16 ].

  • Posh's test does treat 0x10, 020 and 16 as being pairwise -eq. ATT ksh, mksh, dash, bash, zsh, BusyBox and GNU test all treat 020 as -eq to 20. – Gilles Sep 26 '15 at 22:39
2

You could always use printf to convert to decimal and compare that as @ott-- suggested:

[ $(printf "%d" "$hex_string_1") -eq $(printf "%d" "$hex_string_2") ] && echo y

Or

if [ $(printf "%d" "$hex_string_1") -eq $(printf "%d" "$hex_string_2") ]
then
    echo y
fi

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.