Search code examples
bashif-statementsyntaxarithmetic-expressions

Arithmetic expression inside [[


I have this code:

fruit=apple
flag=0

[[ $fruit = "apple" && ((flag == 0)) ]]  && echo "1"
[[ $fruit = "apple" && (($flag == 0)) ]] && echo "2"
[[ $fruit = "apple" && ((! flag)) ]]     && echo "3"
[[ $fruit = "apple" && ((! $flag)) ]]    && echo "4"

All of them are expected to echo something. However, only the second statement works properly:

[[ $fruit = "apple" && (($flag == 0)) ]] && echo "2"

Why is this? Won't arithmetic expressions work properly inside [[ ]]?


Solution

  • The == works the same as = - it is a string comparision.

    The ( ) inside [[ ]] is used to nest expressions. Ex. [[ a = a && (b = b || c = d) ]]

    A non empty string is true. So [[ some_string ]] or [[ "some other string" ]] returns true. [[ "" ]] or [[ '' ]] returns false.

    The ! is negation.

    [[ $fruit = "apple" && ((flag == 0)) ]]
    

    First the expansion of $fruit happens. So it becomes: [[ "apple" = "apple" && ( ( "flag" == "0" ) ) ]]. The ( ) are just braces, this is not arithemtic expansion. The string "apple" is equal to "apple", but the string "flag" is not equal to string "0", so it always returns with false.

    [[ $fruit = "apple" && (($flag == 0)) ]]
    

    Because $flag is expanded, the [[ sees: [[ "apple" = "apple" && ((0 == 0)) ]]. So the comparision happens to work, however == is doing string comparision.

     [[ $fruit = "apple" && ((! flag)) ]]
    

    The flag is a nonempty string, so it evaulates to true. The ! flag evaulates to false.

     [[ $fruit = "apple" && ((! $flag)) ]]
    

    First $flag is expanded to 0. As 0 is a nonempty string, it evaluates to true. The ! 0 evaluates to false. The ((! 0)) is false, so the whole expression returns nonzero.

    Won't arithmetic expressions work properly inside [[ ]]?

    No, arithmetic expressions will not work inside [[ ]] the same way [[ echo 1 ]] does not work. The echo 1 ]] are arguments of [[ builtin, not a standalone command. The same way [[ (( 0 )) ]] the (( 0 )) ]] are interpreted as arguments to [[.