我想
[ 1 -eq $1 ] && echo "yes" || echo "no"
行为就像
if [ 1 -eq $1 ]; then
echo "yes"
else
echo "no"
fi
但是,当我运行这个脚本时(nocmd
是一个不存在的命令)
#!/bin/bash
[ 1 -eq $1 ] && nocmd "yes" || echo "no"
我得到参数“1”的奇怪输出:
me@ubuntu:/tmp$ ./ddd.sh 0
no
me@ubuntu:/tmp$ ./ddd.sh 1
./sh.sh: line 3: nocmd: command not found
no
看起来它的作用是这样的:
if [ 1 -eq $1 ]; then
nocmd "yes"
if [ $? -ne 0 ]; then
echo "no"
fi
else
echo "no"
fi
还好吗?我错过了什么吗?
答案1
除了整体退出状态外,它的行为如下:
if
! {
[ 1 -eq $1 ] && nocmd "yes"
}
then
echo no
fi
在:
A || B
B
当且仅当失败时执行A
。这是一个 OR 运算符。
在您的情况下A
,iff 成功运行[ 1 -eq $1 ] && nocmd "yes"
(AND 运算符),在这种情况下, 的退出状态将是 的退出状态。换句话说,如果或失败,则会执行(请记住,只有成功时才会运行)。nocmd
[
A
nocmd
echo no
[
nocmd "yes"
nocmd
[
这些x && y || z
都是肮脏的黑客行为。正是出于这个原因,最好避免使用它们。如果您确实需要 if/then/else 逻辑,请使用if
//构造。仅当您想要时才使用,除非和都成功。then
else
x && y || z
z
x
y
即使在:
cmd && echo OK || echo >&2 KO
在某些病理条件下可能echo OK
会失败(例如标准输出进入完整文件系统上的文件),并且echo >&2 KO
最终也可能被执行。
$ bash -c 'true && echo OK || echo KO >&2' > /dev/full
bash: line 0: echo: write error: No space left on device
KO
答案2
好吧,实际发生的事情是这样的(这就是如何&&
工作||
的)
test 1 -eq $1
ret=$?
if [ $ret -eq 0 ]; then
nocmd "yes"
ret=$?
fi
if [ $ret -ne 0 ]; then
echo "no"
fi
在你的情况下,如果$1
不等于1
,或不是有效号码,那么你有一个非零$?
,第一个if
被跳过,第二个if
打印“no”。如果$1
equals 1
,则nocmd "yes"
执行,返回非零$?
,并且也会回显“no”。
答案3
您缺少的是对左侧命令的退出状态进行操作 - 左关联性&&
。当且仅当该组命令返回非成功退出状态时, ||
您有here some group of commands || echo "no"
, and才会被回显。no
那组命令是什么?在第一种情况下,你有[ 1 -eq "$1" ] && echo "yes"
.如果[
部分失败,则会被视为失败退出状态[ 1 -eq "$1" ] && echo "yes"
,因此您echo "no"
将运行。另外由于左关联性,当“$1”为1时, [ 1 -eq $1 ]
返回成功,然后让nocmd
运行不存在的shell,shell将返回错误退出状态,整个组将具有失败退出状态,因此回显`“no” 。
相比之下,在你的 if 语句中
if [ 1 -eq $1 ]; then
echo "yes"
else
echo "no"
fi
采取哪条路线仅取决于[
部分的退出状态。在[ 1 -eq "$1" ] && echo "Yes" || echo "no"
echo 中也起着决定是否echo "no"
运行的作用。
你的第二个 if 语句示例也不同
if [ 1 -eq $1 ]; then
nocmd "yes"
if [ $? -ne 0 ]; then
echo "no"
fi
else
echo "no"
fi
after 并不取决于逻辑运算符链接中发生echo "no"
的情况。当然,您在执行完之后仍然执行该部分,但是这里它的退出状态没有与其所属的整个部分分组在一起。else
nocmd
echo "no"
nocmd
if