当前位置:  开发笔记 > 编程语言 > 正文

为什么这个Bash脚本没有错误?

如何解决《为什么这个Bash脚本没有错误?》经验,为你挑选了2个好方法。

这是我的Bash脚本:

#!/bin/bash -e

if [ == "" ]; then
  echo "BAD"
  exit 1
fi

echo "OK"

这是输出:

./test.sh: line 3: [: ==: unary operator expected
OK

返回码为0.

在第3行有一个明显的语法错误.而不是提出语法错误并拒绝运行脚本,不知何故脚本运行并在运行时报告语法错误.该-e标志并未保护我 - 显然if语句中的语法错误构成错误条件而不是立即退出程序的理由.但是,不知怎的,Bash 已经解析了整个if ... fi块,所以在忽略坏线之后,执行会以某种方式恢复,而不是在下一个语法正确的行但是在块结束之后?

我有两个问题:

    到底是怎么回事?

    我将来如何保护自己免受这种行为的影响?

Biffen.. 15

    if运行命令[,只检查其返回码.Bash不知道也不关心[命令的语法.

    你可以在那里放一些其他的命令,Bash仍然不会知道它的特定语法.

    我想到两件事:

    使用[[而不是[:Bash 确实知道并关心它的语法.

    使用ShellCheck 1 ; 在线,手动或在您喜欢的编辑器中.

双方if-e处理退出代码:如果是非零if不会让你变成then块,并且-e将退出.你不可能同时拥有这两种行为.(嗯,这似乎 [退出提供虚假结果(1)和语法错误(2)不同的代码,所以它可能是有可能为"检测"语法错误.)


1或其他一些工具,但这是我所知道的唯一一个.建议欢迎.



1> Biffen..:

    if运行命令[,只检查其返回码.Bash不知道也不关心[命令的语法.

    你可以在那里放一些其他的命令,Bash仍然不会知道它的特定语法.

    我想到两件事:

    使用[[而不是[:Bash 确实知道并关心它的语法.

    使用ShellCheck 1 ; 在线,手动或在您喜欢的编辑器中.

双方if-e处理退出代码:如果是非零if不会让你变成then块,并且-e将退出.你不可能同时拥有这两种行为.(嗯,这似乎 [退出提供虚假结果(1)和语法错误(2)不同的代码,所以它可能是有可能为"检测"语法错误.)


1或其他一些工具,但这是我所知道的唯一一个.建议欢迎.


@qntm它是[`test`](http://linux.die.net/man/1/test)命令的另一种形式.

2> Etan Reisner..:

这里没有shell语法错误.

[命令/ builtin 的参数中有错误.

set -e这里没有帮助的原因是因为那显然不是它应该做的.如果您的代码中没有语句,那set -e将变得完全没用if.试想一下.

如果您在POSIX规范中查看-e/ errexitflag的内容,您会看到以下描述:

-e

当此选项打开时,当任何命令失败时(由于Shell错误的后果中列出的任何原因或返回大于零的退出状态),shell将立即退出并出现以下异常:

    多命令管道中任何单个命令的失败都不会导致shell退出.只考虑管道本身的故障.

    -e设置应执行以下化合物列表时,可以忽略不计,同时,直到,如果,或ELIF保留字,管道开始用!保留字,或除最后一个之外的AND-OR列表的任何命令.

    如果除了子shell命令之外的复合命令的退出状态是在忽略-e时失败的结果,则-e不应用于此命令.

此要求分别适用于shell环境和每个子shell环境.例如,在:

set -e; (false; echo one) | cat; echo two

看点二吗?那是你的情况.

shell继续执行的原因是"不是shell语法错误".您有一个命令错误.该[命令/内建试图解析它的参数和失败.然后它返回一个错误返回码.该if抓的是,跳过它的身体并返回true(按照中记录的行为if时,没有条件返回true).所以shell脚本继续正常.

然而,正如我在评论中指出的那样,如果你曾经使用过[[(这是一个bash-ism和一个语言结构)那么你的脚本会出现语法错误并且会立即退出该行(至少在我的测试中).

推荐阅读
重庆制造漫画社
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有