在Bash脚本中否定条件

241

我卡在了尝试否定以下命令的过程中:

wget -q --tries=10 --timeout=20 --spider http://google.com
if [[ $? -eq 0 ]]; then
        echo "Sorry you are Offline"
        exit 1

如果我连接到互联网,此 if 条件将返回 true。我希望它相反,但是任何地方放置 ! 似乎都不起作用。


4
你把它放在哪了?if ! [[ ... 有效。 - that other guy
1
你也可以这样使用它:wget your_xxxx_params ||(echo“oh oh”&& exit 1) - AKS
2
为了输出一个错误,调用一个子shell - tijagi
为什么测试“$?”来查看命令是否成功是一种反模式? - tripleee
5个回答

326

您可以选择:

if [[ $? -ne 0 ]]; then       # -ne: not equal

if ! [[ $? -eq 0 ]]; then     # -eq: equal

if [[ ! $? -eq 0 ]]; then

! 反转下一个表达式的返回值。


18
需要使用双括号吗?为什么? - Alexander Mills
3
@AlexanderMills:有几种方法可以实现这个。使用双括号或单括号,或者使用test命令: if test $? -ne 0; then - Cyrus
18
这个答案有点啰嗦。if 需要一个结果为 0 或者 1 的语句,所以你可以直接使用命令并将其反转:if ! wget ...; then ...; fi。请注意,我的翻译旨在使原文更易理解,但不改变其意思。 - Nils Magnus

124

更好

if ! wget -q --spider --tries=10 --timeout=20 google.com
then
  echo 'Sorry you are Offline'
  exit 1
fi

5
重要提示:在 ! 和下一个命令之间保留空格,否则将进行历史扩展操作。https://unix.stackexchange.com/questions/3747/understanding-the-exclamation-mark-in-bash - Roland
3
为什么你的声望值只有1,Steven? - Roland
1
看起来 Steven 被禁止了 - 如果你查看他的个人资料,会发现他被暂停直到2022年秋季。 - Geoff Davids

9

如果你感到懒惰,这里有一种简洁的处理条件的方法,使用操作后的||(或)和&&(与):

wget -q --tries=10 --timeout=20 --spider http://google.com || \
{ echo "Sorry you are Offline" && exit 1; }

13
在实际脚本中,你应该将 echo 命令后面的 && 改为 ; 。原因是如果输出被重定向到满盘的文件上,echo 将返回失败,而 exit 永远不会触发。这可能不是你想要的行为。 - Score_Under
1
你可以使用 set -e,如果失败,echo 也会退出脚本。 - Jakub Bochenski

8
你可以使用不等比较运算符-ne代替-eq:
wget -q --tries=10 --timeout=20 --spider http://google.com
if [[ $? -ne 0 ]]; then
    echo "Sorry you are Offline"
    exit 1
fi

5

由于您正在比较数字,因此可以使用算术表达式进行处理参数和比较。可以使用条件语句来实现。

wget -q --tries=10 --timeout=20 --spider http://google.com
if (( $? != 0 )); then
    echo "Sorry you are Offline"
    exit 1
fi

注意,你可以使用!=来代替-ne。在算术上下文中,我们甚至不需要在参数前面加上$,即
var_a=1
var_b=2
(( var_a < var_b )) && echo "a is smaller"

程序运行完全正常,但是这并不适用于$?特殊参数。

此外,由于(( ... ))将非零值计算为真,即对于非零值具有返回状态0,否则返回状态1,因此我们可以缩短代码:

if (( $? )); then

但是,这可能会让更多的人感到困惑,而节省的按键并不值得。
在Bash中,(( ... ))结构是可用的,但不是POSIX shell规范所必需的(尽管被提及为可能的扩展)。
话虽如此,在我看来最好还是避免使用$?,如Cole's answerSteven's answer

你确定要使用 (( ... )) 吗?POSIX程序员参考 - 复合命令 - David C. Rankin
@DavidC.Rankin 噢,我没有找到那个!所以它被提及为扩展,但不是必需的。我会修订一下。 - Benjamin W.
1
是的,那个也总是让我困扰。不过在 shell 中确实可以让生活更轻松 :) - David C. Rankin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接