'Bash: how to evaluate results of commands inside double brackets

I guess mytrue and myfalse are considered strings instead of commands:

myfalse () {
    return 0
}

mytrue () {
    return 1
}

test-conditional ( ) {
    SHOW="dont-show"
    [[ ${SHOW} == "show" || mytrue ]] && echo "ok" || echo "wrong"
    [[ ${SHOW} == "show" && mytrue ]] && echo "err" || echo "ok"
    [[ ${SHOW} == "show" || myfalse ]] && echo "err" || echo "ok"
    [[ ${SHOW} == "show" && myfalse ]] && echo "err" || echo "ok"
    SHOW="show"
    [[ ${SHOW} == "show" || mytrue ]] && echo "ok" || echo "err"
    [[ ${SHOW} == "show" && mytrue ]] && echo "ok" || echo "err"
    [[ ${SHOW} == "show" || myfalse ]] && echo "ok" || echo "err"
    [[ ${SHOW} == "show" && mytrue ]] && echo "err" || echo "ok"

}

test-conditional

So this is showing wrong output:

ok
ok
err
ok
ok
ok
ok
err

(It should be ok everywhere)

How can evaluate commands inside double brackets?



Solution 1:[1]

You have true and false functions returning opposite return codes and your last condition needs a correction.

You can use:

myfalse () {
   return 1
}

mytrue () {
   return 0
}

test-conditional ( ) {
    SHOW="dont-show"
    [[ ${SHOW} == "show" ]] || mytrue && echo "ok" || echo "wrong"
    [[ ${SHOW} == "show" ]] && mytrue && echo "err" || echo "ok"
    [[ ${SHOW} == "show" ]] || myfalse && echo "err" || echo "ok"
    [[ ${SHOW} == "show" ]] && myfalse && echo "err" || echo "ok"
    SHOW="show"
    [[ ${SHOW} == "show" ]] || mytrue && echo "ok" || echo "err"
    [[ ${SHOW} == "show" ]] && mytrue && echo "ok" || echo "err"
    [[ ${SHOW} == "show" ]] || myfalse && echo "ok" || echo "err"
    [[ ${SHOW} == "show" ]] && myfalse && echo "err" || echo "ok"
}

test-conditional

Also note how function call is placed outside [[ ... ]] otherwise it won't invoke function.

Following rules apply while evaluating these expressions:

  1. Condition after && isn't evaluated if first condition fails.
  2. Condition after || isn't evaluated if first condition succeeds.

Solution 2:[2]

Inside a bash [[…]] (and inside the older […] in most shells) what matters is if the value tested has some characters or not:

$ [[ somevalue ]] && echo "yes" || echo "no"

If the value tested if empty, the test fails:

$ [[ "" ]] && echo "yes" || echo "no"
no

That is also true for variables:

$ somevalue="a false string"
$ [[ $somevalue ]] && echo "yes" || echo "no"
yes

$ somevalue=""
$ [[ $somevalue ]] && echo "yes" || echo "no"
no

So, [[…]] is limited to testing strings not "exit codes".
Your functions define "exit codes" not strings.
You may

  1. define the values of mytrue and myfalse to be variables that represent those values:

    mytrue=A_True_Value
    myfalse=""
    

    And use them:

    $ show="dont-show"
    $ [[ ${SHOW} == "show" || $mytrue ]] && echo "ok" || echo "wrong"
    ok
    
    $ [[ ${SHOW} == "show" || $myfalse ]] && echo "ok" || echo "wrong"
    wrong
    
  2. Or, actually test exit codes outside a [[…]] idiom:

    $ mytrue(){ return 0; }
    $ if mytrue; then echo "ok"; else echo "wrong"; fi
    ok
    
    $ mytrue && echo "ok" || echo "wrong"
    ok
    
  3. One (more complex) alternative is to make the functions emit a value and call the execution of the code in the functions from the [[…]] idiom:

    $ mytrue(){ echo "A_True_Value"; }
    $ myfalse(){ echo ""; }
    $ show="dont-show"
    $ [[ ${SHOW} == "show" || $(mytrue) ]] && echo "ok" || echo "wrong"
    ok
    

KISS

But (probably) the simplest of solutions is the best solution:

myfalse=""
mytrue="true"

test-conditional () {
    show="dont-show"
    [[ ${show} == "show" || $mytrue  ]] && echo "ok"  || echo "wrong"
    [[ ${show} == "show" && $mytrue  ]] && echo "err" || echo "ok"
    [[ ${show} == "show" || $myfalse ]] && echo "err" || echo "ok"
    [[ ${show} == "show" && $myfalse ]] && echo "err" || echo "ok"
    show="show"
    [[ ${show} == "show" || $mytrue  ]] && echo "ok"  || echo "err"
    [[ ${show} == "show" && $mytrue  ]] && echo "ok"  || echo "err"
    [[ ${show} == "show" || $myfalse ]] && echo "ok"  || echo "err"
    [[ ${show} == "show" && $myfalse ]] && echo "err" || echo "ok"
}

test-conditional

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 done