Bash条件基于退出命令代码

Luk*_*non 2 bash shell command process exit-code

在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
Run Code Online (Sandbox Code Playgroud)

success.sh

#!/bin/bash

exit 0
Run Code Online (Sandbox Code Playgroud)

failure.sh

#!/bin/bash

exit 1
Run Code Online (Sandbox Code Playgroud)

这应打印出来:

First: success!
Second: failure!
Run Code Online (Sandbox Code Playgroud)

我怎么做到这一点?谢谢!

Gor*_*son 7

只需删除括号:

#!/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
Run Code Online (Sandbox Code Playgroud)

说明:间推移的事情if并且then是一个命令(或一系列命令),该退出状态被用于确定是否运行该then子句或else子句.这正是你想要的.

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

顺便说一下,你有时也会看到if [[ some expression ]]; thenif (( some expression )); then.[[ ]]并且(( ))是bash语法中内置的条件表达式(与[命令不同).[[ ]]本质上是一个更好的版本[ ](清除了一些语法奇怪和添加了一些功能),并且(( ))是一个有点类似的算法表达式构造.

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

somecommand
if [ $? -eq 0 ]; then
    echo "Somecommand: success!"
else
    echo "Somecommand: failure!"
fi
Run Code Online (Sandbox Code Playgroud)

我真的认为这个货物崇拜节目.人们习惯于[ ]if语句中看到条件表达式,这个习惯用法将成功测试放在条件表达式的形式中.但是让我来看看它是如何工作的:它接受命令的退出状态,将其置于条件表达式中,[ ]对其进行评估并将其右转回到退出状态,以便if可以使用它.整个过程是不必要的; 只需将命令直接放在if语句中即可.

  • @ChristianLong 是的,这很令人困惑。shell 约定以这种方式工作,因为退出代码 0 表示命令成功,并且成功是“truthy”,因此(在退出代码上下文中)0 必须是“truthy”(非零表示失败,因此必须是“虚假的”)。IMO 最容易考虑命令成功与失败,而不是零与非零;这是将命令直接放在“if”语句中的另一个优点。 (4认同)
  • 请注意,bash `if` 的工作方式有点奇怪。退出代码为零会导致 bash 采用“if”分支,非零退出代码会导致 bash 采用“else”分支。这与其他语言相反,在其他语言中,零是“假”,非零是“真”。http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html (2认同)
  • @ricab如果你想检测特定的错误状态,你需要先运行命令,然后检查“$?”,比如“git diff --quiet;” if (( $? == 1 ))` (如果您想进行多次检查,请先将其存储在变量中)。请参阅我的答案[此处](/sf/ask/4342361831/#62033933)。 (2认同)

miv*_*ivk 6

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

(( ))以下是使用您的命令和 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
Run Code Online (Sandbox Code Playgroud)