Bash:如何评估双括号内的命令结果

时间:2017-01-12 10:49:21

标签: bash conditional logical-operators

我猜mytruemyfalse被视为字符串而不是命令:

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

所以这显示了错误的输出:

ok
ok
err
ok
ok
ok
ok
err

(到处都是ok

如何评估双括号内的命令?

2 个答案:

答案 0 :(得分:4)

您有truefalse个函数返回相反的返回代码,您的上一个条件需要更正。

您可以使用:

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

另请注意函数调用如何放在[[ ... ]]之外,否则它不会调用函数。

在评估这些表达式时适用以下规则:

  1. 如果第一个条件失败,则&&之后的条件不会被评估。
  2. 如果第一个条件成功,则||之后的条件不会被评估。

答案 1 :(得分:1)

在bash [[…]]内部(以及大多数shell中较旧的[…]内部)重要的是,如果测试的值有某些字符:

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

如果测试的值为空,则测试失败:

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

变量也是如此:

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

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

因此,[[…]]仅限于测试字符串而不是"退出代码" 您的函数定义"退出代码"不是字符串。
你可以

  1. mytruemyfalse的值定义为代表这些值的变量:

    mytrue=A_True_Value
    myfalse=""
    

    并使用它们:

    $ show="dont-show"
    $ [[ ${SHOW} == "show" || $mytrue ]] && echo "ok" || echo "wrong"
    ok
    
    $ [[ ${SHOW} == "show" || $myfalse ]] && echo "ok" || echo "wrong"
    wrong
    
  2. 或者,实际测试[[…]]成语之外的退出代码:

    $ mytrue(){ return 0; }
    $ if mytrue; then echo "ok"; else echo "wrong"; fi
    ok
    
    $ mytrue && echo "ok" || echo "wrong"
    ok
    
  3. 一个(更复杂的)替代方法是让函数发出一个值,并从[[…]]成语中调用函数中代码的执行:

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

    但(可能)最简单的解决方案是最佳解决方案:

    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