[bash] Shell equality operators (=, ==, -eq)

It depends on the Test Construct around the operator. Your options are double parentheses, double brackets, single brackets, or test.

If you use (()), you are testing arithmetic equality with == as in C:

$ (( 1==1 )); echo $?
0
$ (( 1==2 )); echo $?
1

(Note: 0 means true in the Unix sense and a failed test results in a non-zero number.)

Using -eq inside of double parentheses is a syntax error.

If you are using [] (or single brackets) or [[]] (or double brackets), or test you can use one of -eq, -ne, -lt, -le, -gt, or -ge as an arithmetic comparison.

$ [ 1 -eq 1 ]; echo $?
0
$ [ 1 -eq 2 ]; echo $?
1
$ test 1 -eq 1; echo $?
0

The == inside of single or double brackets (or the test command) is one of the string comparison operators:

$ [[ "abc" == "abc" ]]; echo $?
0
$ [[ "abc" == "ABC" ]]; echo $?
1

As a string operator, = is equivalent to ==. Also, note the whitespace around = or ==: it’s required.

While you can do [[ 1 == 1 ]] or [[ $(( 1+1 )) == 2 ]] it is testing the string equality — not the arithmetic equality.

So -eq produces the result probably expected that the integer value of 1+1 is equal to 2 even though the right-hand side is a string and has a trailing space:

$ [[ $(( 1+1 )) -eq  "2 " ]]; echo $?
0

While a string comparison of the same picks up the trailing space and therefore the string comparison fails:

$ [[ $(( 1+1 )) == "2 " ]]; echo $?
1

And a mistaken string comparison can produce a completely wrong answer. 10 is lexicographically less than 2, so a string comparison returns true or 0. So many are bitten by this bug:

$ [[ 10 < 2 ]]; echo $?
0

The correct test for 10 being arithmetically less than 2 is this:

$ [[ 10 -lt 2 ]]; echo $?
1

In comments, there is a question about the technical reason why using the integer -eq on strings returns true for strings that are not the same:

$ [[ "yes" -eq "no" ]]; echo $?
0

The reason is that Bash is untyped. The -eq causes the strings to be interpreted as integers if possible including base conversion:

$ [[ "0x10" -eq 16 ]]; echo $?
0
$ [[ "010" -eq 8 ]]; echo $?
0
$ [[ "100" -eq 100 ]]; echo $?
0

And 0 if Bash thinks it is just a string:

$ [[ "yes" -eq 0 ]]; echo $?
0
$ [[ "yes" -eq 1 ]]; echo $?
1

So [[ "yes" -eq "no" ]] is equivalent to [[ 0 -eq 0 ]]


Last note: Many of the Bash specific extensions to the Test Constructs are not POSIX and therefore may fail in other shells. Other shells generally do not support [[...]] and ((...)) or ==.