为什么在`||`之后执行命令,即使先前命令成功?

问题描述 投票:1回答:2

我在bash函数中使用短路评估(使用&&||),我不明白我看到的行为。如果第一个数字不大于第二个,我希望函数返回:

[[ 5 > 2 ]] && echo true || echo false && return

#    ^             ^                   ^
# true so       do this        not this && this


[[ 5 > 8 ]] && echo true || echo false && return

#    ^             ^                   ^ 
# false so   don't do this      do this && this

但是在任何一种情况下函数都会返回无论第一个命令的状态如何,为什么return命令都会执行?

而不是return我尝试了break,但由于不在循环内,它不起作用。

  1. 为什么return似乎在这两种情况下执行?
  2. 我怎样才能结束运行功能?
bash operators
2个回答
4
投票
    stmt1  &&  stmt2    ||  stmt3    &&  stmt4

被评估为

( ( stmt1  &&  stmt2 )  ||  stmt3 )  &&  stmt4

即从左到右。

所以逻辑是

Execute stmt1
If it succeeds,
then
    execute stmt2
endif
If stmt1 succeeds and stmt2 succeeds,
then
    (do nothing here)
else                    # i.e., if stmt1 fails,  OR  stmt1 succeeds and then stmt2 fails
    execute stmt3
endif
If stmt1 succeeds and stmt2 succeeds,
                  OR  stmt3 succeeds,
then
    execute stmt4
endif

由于stmt2stmt3都是echo语句,它们都总是成功,所以stmt4return语句)总是被执行。

我怀疑你在期待

( stmt1  &&  stmt2 )  ||  ( stmt3  &&  stmt4 )

并且您可以通过键入括号来获得该行为(通常),就像这样:

 ( [[ 5 > N ]] && echo true )  ||  ( echo false && return )         # No, don’t do this

或括号:

{ [[ 5 > N ]] && echo true; }  ||  { echo false && return; }

请注意,在{}之前的分号后必须有空格。

还要注意,使用括号,命令在子shell中运行,而使用大括号,它们不会(它们在主shell上下文中运行)。在您的特定代码示例中,您必须使用大括号(至少对于||之后的部分),因为return在子shell中运行时没有任何效果。


2
投票

使用if而不是逻辑运算符。

if [[ 5 > 8 ]]
then echo true
else
    echo false
    return
fi

有关运算符如何组合的说明,请参阅precedence of the shell logical operators

© www.soinside.com 2019 - 2024. All rights reserved.