在bash中编写if
个阻止时,shellcheck告诉我&&
和||
首选使用-a
和-o
。< / p>
为什么呢?它更快,或者只是简单的风格偏好使脚本看起来更干净?
我得到的具体信息是:
^-- SC2166: Prefer [ p ] || [ q ] as [ p -o q ] is not well defined.
答案 0 :(得分:8)
来自the POSIX specification for test
:
4个论点:
结果未明确。
[OB XSI] [选项开始]在符合XSI的系统上,应使用前面描述的优先级和关联性规则评估原色和运算符的组合。此外,字符串比较二进制初级'='和“!=”应优先于任何一元初级。 [选项结束]
因此:test
使用超过三个参数 - 如果您使用-a
或-o
,则依赖于此 - 没有明确指定的行为由未扩展的POSIX。
现在,为什么会这样呢?因为有些情况下解析器可以根据变量值执行错误的操作。
你还记得有人建议做这样的事吗?
if [ "x$foo" = "x$bar" ]; then ...
......这是愚蠢而古老的,对吗?实际上,没有!考虑foo=(
和bar=)
的情况,有人运行这样的命令:
if [ "$foo" -a "$bar" ]
扩展到以下内容:
if [ ( -a ) ]
......我们如何解析它?好吧,可能是一个分组运算符(是的,test
在历史上被指定为支持它们),检查-a
是否为非空;或者可以检查(
和)
本身是非空字符串;这是模棱两可的。这种含糊不清是-a
和-o
不再是首选语法的原因。
那么,替换是什么样的?而不是:
[ "$foo" -gt "$bar" -a "$foo" -lt "$qux" ]
...你写的是:
[ "$foo" -gt "$bar" ] && [ "$foo" -lt "$qux" ]
...关闭两个测试表达式并使用shell语法组合它们的输出。由于[
/ test
是内置的shell,因此不需要将其作为外部命令执行,因此这不会产生70年代运行时的性能开销。 test
意味着调用/usr/bin/test
。