看看这些尝试:
$ case `true` in 0) echo success ;; *) echo fail ;; esac
fail
$ if `true` ; then
> echo "success"
> else
> echo "fail"
> fi
success
现在,为什么案例陈述失败了?您可能想知道为什么我不直接使用该if
声明,我将对此进行解释。我的命令如果很复杂,可能会返回我想要执行的不同返回代码。我不想多次运行该命令,但我不能这样做:
my_command
res = $?
case $? in
...
esac
这是因为我set -e
在脚本中使用,因此如果my_command
返回失败,脚本将中止。
但我有一个解决方法...
set +e
my_command
res=$?
set -e
case $? in
...
esac
但这很丑陋,所以回到我最初的问题......为什么我只能使用该case my_command in ... esac
版本?
答案1
你不能使用
case $(somecommand) in ...
测试退出状态,somecommand
因为命令替换扩展到命令的输出,而不是其退出状态。
使用$(true)
不起作用,因为true
不会在标准输出上产生任何输出。
你可以做
{ somecommand; err="$?"; } || true
case $err in
0) echo success ;;
*) echo fail
esac
errexit
这将阻止( )下运行的脚本-e
退出。
从bash
手册(从描述set -e
):
如果失败的命令是紧随 while 或until 关键字之后的命令列表的一部分,是 if 或 elif 保留字之后的测试的一部分,则 shell 不会退出,在 && 或 || 中执行的任何命令的一部分列出最后 && 或 || 后面的命令除外、管道中除最后一个命令之外的任何命令,或者命令的返回值与 ! 反转。
在这种情况下,只有成功或失败的可能性,这样做会更容易
if somecommand; then
echo success
else
echo fail
fi
答案2
语法
`command`
意思是把命令的标准输出替换成原来的命令行。输出与退出状态不同。该true
命令不会产生任何输出,因此您的命令相当于:
case "" in
0) echo success ;;
*) echo fail ;;
esac
您可以这样解决您的问题:
case `my_command; echo $?` in
...
esac
顺便说一句,在if
命令中你不需要反引号,它应该是:
if true
then echo successs
else echo fail
fi
答案3
即使set -e
你仍然可以这样做:
if my_command
then
echo success
else
res=$?
case $res in
…
esac
fi
编辑:你也可以这样做
res=0
my_command || res=$?
case $res in
…
esac
答案4
我完全同意;禁用 -e 并重新启用它是丑陋的,应该避免。
几个选项
if my_command; then
echo "my_command ran ok"
else
rc=$?
echo "my_command exited with error code $rc"
fi
或者,如果您想走案例路线(这有点hacky,但它应该显示功能而不是使用)。
# PLEASE DO NOT ACTUALLY DO THIS
case "$(my_command > /dev/null && echo 0 || echo $?)" in
0) echo yeah ;;
11) echo "bummer" ;;
*) echo meh ;;
esac
一个不太难看的解决方案可能是(如果你想使用案例)
my_command && rc=0 || rc=1
case "$rc" in
...
esac