【问题标题】:Understanding Bash short-circuiting了解 Bash 短路
【发布时间】:2016-06-14 05:22:52
【问题描述】:

首先,我不是 Bash 专业人士。几个月前我发现,如果我将&&|| 短路运算符按顺序与花括号一起使用,那么如果第一个语句以真实值退出,如果真块中的最后一个语句退出非零,那么失败块也将被执行。像这样:

returnNumber 0 && {
    echo 'OK'
    returnNumber 1
} || {
    echo 'NG'
}

将输出:

OK
NG

所以,我为此寻找了最简单的解决方案,并想出了这个:

returnNumber 0 && {
    echo 'OK'
    returnNumber 1
    :
} || {
    echo 'NG'
}

我知道,省略内置冒号很容易,但它是解决方法的正确方法吗?

【问题讨论】:

  • 不要把使用特殊语法作为一项运动。当您只写if-then-else-fi 时,大多数人都会理解。尝试考虑有效的例外情况。我仍然不确定我的答案stackoverflow.com/a/28478184/3220113:它有效但难以阅读。
  • 这个上下文中的大括号是什么语法?

标签: linux bash short-circuiting


【解决方案1】:

先生。 Llama 已经正确回答了这个问题,这只是为了快速参考不同“组合”会发生什么。 cmd0 是退出状态为零的“命令”,cmd1 是非零退出状态。

cmd0() { echo -n "[$@-0]"; return 0; }
cmd1() { echo -n "[$@-1]"; return 1; }
second() { echo "[second]"; }

doit() { echo "case: $@"; eval "$@"; echo; }

doit 'cmd0 start && cmd0 first && second'
doit 'cmd0 start && cmd0 first || second'
doit 'cmd0 start || cmd0 first && second'
doit 'cmd0 start || cmd0 first || second'

doit 'cmd0 start && cmd1 first && second'
doit 'cmd0 start && cmd1 first || second'
doit 'cmd0 start || cmd1 first && second'
doit 'cmd0 start || cmd1 first || second'

doit 'cmd1 start && cmd0 first && second'
doit 'cmd1 start && cmd0 first || second'
doit 'cmd1 start || cmd0 first && second'
doit 'cmd1 start || cmd0 first || second'

doit 'cmd1 start && cmd1 first && second'
doit 'cmd1 start && cmd1 first || second'
doit 'cmd1 start || cmd1 first && second'
doit 'cmd1 start || cmd1 first || second'

产生:

case: cmd0 start && cmd0 first && second
[start-0][first-0][second]

case: cmd0 start && cmd0 first || second
[start-0][first-0]

case: cmd0 start || cmd0 first && second
[start-0][second]

case: cmd0 start || cmd0 first || second
[start-0]

case: cmd0 start && cmd1 first && second
[start-0][first-1]

case: cmd0 start && cmd1 first || second
[start-0][first-1][second]

case: cmd0 start || cmd1 first && second
[start-0][second]

case: cmd0 start || cmd1 first || second
[start-0]

case: cmd1 start && cmd0 first && second
[start-1]

case: cmd1 start && cmd0 first || second
[start-1][second]

case: cmd1 start || cmd0 first && second
[start-1][first-0][second]

case: cmd1 start || cmd0 first || second
[start-1][first-0]

case: cmd1 start && cmd1 first && second
[start-1]

case: cmd1 start && cmd1 first || second
[start-1][second]

case: cmd1 start || cmd1 first && second
[start-1][first-1]

case: cmd1 start || cmd1 first || second
[start-1][first-1][second]

【讨论】:

    【解决方案2】:

    这其实是一个很常见的Bash pitfall。这不是错误。

    returnNumber 0 的计算结果为真,因此第二个块(由逻辑和 && 连接)也被计算以确保 first && second 的结果仍然为真。
    第二个块输出OK 但计算结果为假,所以现在first && second 的结果为假。这意味着第三部分(由逻辑或|| 连接)也必须被评估,从而导致NG 也被显示。


    您应该使用if 语句,而不是依赖&&||

    if returnNumber 0; then
        echo 'OK'
        returnNumber 1
    else
        echo 'NG'
    fi
    

    tl;dr:y 可以返回非零退出状态时,切勿使用x && y || z

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-15
    • 1970-01-01
    • 1970-01-01
    • 2015-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多