在 bash 中编写if
块时,shellcheck告诉我&&
and||
比使用-a
and更受欢迎-o
。
为什么?它更快,还是只是为了使脚本看起来更干净的风格偏好?
我得到的具体信息是:
^-- SC2166: Prefer [ p ] || [ q ] as [ p -o q ] is not well defined.
在 bash 中编写if
块时,shellcheck告诉我&&
and||
比使用-a
and更受欢迎-o
。
为什么?它更快,还是只是为了使脚本看起来更干净的风格偏好?
我得到的具体信息是:
^-- SC2166: Prefer [ p ] || [ q ] as [ p -o q ] is not well defined.
来自POSIX 规范test
:
4个论点:
结果未指定。
[OB XSI] [选项开始] 在符合 XSI 的系统上,应使用前面描述的优先级和关联性规则来评估初级和运算符的组合。此外,字符串比较二元基元 '=' 和 "!=" 应具有比任何一元基元更高的优先级。[选项结束]
因此: 使用test
三个以上的参数——如果你使用-a
or -o
,你依赖它——没有未扩展的 POSIX 明确指定的行为。
现在,为什么会这样?因为在某些情况下,解析器可能会根据变量值做错事。
你还记得有人建议做这样的事情吗?
if [ "x$foo" = "x$bar" ]; then ...
......这是愚蠢和古老的,对吧?其实,不!foo=(
考虑and的情况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
.