【问题标题】:Bash conditional based on exit code of command基于命令退出代码的 Bash 条件
【发布时间】:2018-09-25 18:13:09
【问题描述】:

在 Bash 中,我想要一个基于运行命令的退出代码的 if 语句。例如:

#!/bin/bash

if [ ./success.sh ]; then
    echo "First: success!"
else
    echo "First: failure!"
fi

if [ ./failure.sh ]; then
    echo "Second: success!"
else
    echo "Second: failure!"
fi

success.sh

#!/bin/bash

exit 0

failure.sh

#!/bin/bash

exit 1

这应该打印出来:

First: success!
Second: failure!

我将如何实现这一目标?谢谢!

【问题讨论】:

标签: bash shell process command exit-code


【解决方案1】:

去掉括号即可:

#!/bin/bash

if ./success.sh; then
    echo "First: success!"
else
    echo "First: failure!"
fi

if ./failure.sh; then
    echo "Second: success!"
else
    echo "Second: failure!"
fi

解释:ifthen之间的东西是一个命令(或一系列命令),它的退出状态用于确定是运行then子句还是else条款。这正是你想要的。

那么为什么人们在if 语句中使用方括号呢?这是因为通常您想根据某些条件表达式("$a" 等于"$b",是否存在某个文件等)来决定运行if 的哪个分支。 [ 实际上是一个命令,它将其参数解析为条件表达式(忽略最后的 ]),然后根据条件是真还是假以成功或失败退出。本质上,[ ] 用作适配器,允许您在if 语句中使用条件表达式而不是命令成功/失败。在您的情况下,您希望成功/失败不是条件表达式,所以不要使用适配器。

顺便说一句,您有时还会看到if [[ some expression ]]; thenif (( some expression )); then[[ ]](( )) 是内置在 bash 语法中的条件表达式(与 [ 不同,它是一个命令)。 [[ ]] 本质上是 [ ] 的更好版本(清理了一些奇怪的语法并添加了一些功能),(( )) 是一个有点相似的算术表达式构造。

顺便说一句,您将在脚本中看到的另一件事是通过检查特殊参数$? 来测试退出状态,该参数给出了最后一个命令的退出状态。它看起来像这样:

somecommand
if [ $? -eq 0 ]; then
    echo "Somecommand: success!"
else
    echo "Somecommand: failure!"
fi

我真的认为这种货物崇拜编程。人们习惯于在if 语句中看到[ ] 条件表达式,而这个成语将成功测试以条件表达式的形式进行。但是让我来看看它是如何工作的:它获取命令的退出状态,将其放入条件表达式中,让[ ] 评估该并将其转回退出状态所以@987654348 @可以使用。整个 rigamarole 是不必要的;只需将命令直接放在if 语句中即可。

【讨论】:

  • 请注意,bash if 的工作方式有些奇怪。退出代码为零导致 bash 采用 if 分支,非零退出代码导致 bash 采用 else 分支。这与其他语言相反,其中零是“虚假”,非零是“真实”。 tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html
  • @ChristianLong 是的,这很令人困惑。 shell 约定以这种方式工作,因为退出代码 0 表示命令成功,并且成功是“真实的”,所以(在退出代码上下文中)0 必须是“真实的”(非零表示失败,所以必须是 '假的')。 IMO 最容易根据命令成功与失败而不是零与非零来思考;这是将命令直接放在if 语句中的另一个优点。
【解决方案2】:

除了接受的答案之外,请注意,您有时可能希望保留退出状态以供以后使用。在这种情况下,您可以将其保存到变量中,然后测试该变量。

这是一个使用您的命令和 Bash 算法 (( )) 命令进行测试的示例:

#!/bin/bash

./success.sh
es1=$?

echo "exit status = $es1"
if (( es1 == 0 )); then
    echo "First: success! (es1 = $es1)"
else
    echo "First: failure! (es1 = $es1)"
fi

./failure.sh
es2=$?

echo "exit status = $es2"
if (( es2 > 0 )); then
    echo "Second: failure! ($es2 is greater than 0)"
else
    echo "Second: success!"
fi

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-12
    • 1970-01-01
    • 1970-01-01
    • 2012-01-02
    • 1970-01-01
    • 2013-08-26
    • 2018-11-04
    • 1970-01-01
    相关资源
    最近更新 更多