如何使用case语句处理多个返回值

如何使用case语句处理多个返回值

看看这些尝试:

$ 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

相关内容