为什么是&&和|| 优先选择-a和-o

Mat*_*bst 4 bash shell shellcheck

if在bash中编写块时,shellcheck告诉我&&并且||更喜欢使用-a-o.

为什么?它更快,或者只是简单的风格偏好使脚本看起来更干净?

我得到的具体信息是:

^-- SC2166: Prefer [ p ] || [ q ] as [ p -o q ] is not well defined.
Run Code Online (Sandbox Code Playgroud)

Cha*_*ffy 9

POSIX规范test:

  • 4个论点:

    结果未指定.

    [OB XSI] [选项开始]在符合XSI的系统上,应使用前面描述的优先级和关联性规则评估原色和运算符的组合.此外,字符串比较二进制初级'='和"!="应优先于任何一元初级.[选项结束]

因此:使用test超过三个参数 - 如果你正在使用-aor -o,你依赖于它 - 没有未扩展POSIX明确指定的行为.


现在,为什么会这样呢?因为有些情况下解析器可以根据变量值执行错误的操作.

你还记得有人建议做这样的事吗?

if [ "x$foo" = "x$bar" ]; then ...
Run Code Online (Sandbox Code Playgroud)

......这很愚蠢和古老,对吧?实际上,!考虑的情况下foo=(bar=),和有人运行如下命令:

if [ "$foo" -a "$bar" ]
Run Code Online (Sandbox Code Playgroud)

这扩展到以下内容:

if [ ( -a ) ]
Run Code Online (Sandbox Code Playgroud)

......我们如何解析它?好吧,它可能是一个分组运算符(是的,test历史上指定支持它们),检查是否-a为非null; 或者它可以检查是否都()非空字符串本身; 这是模棱两可的.这种歧义是为什么-a-o不再是首选语法.


那么,替换是什么样的?代替:

[ "$foo" -gt "$bar" -a "$foo" -lt "$qux" ]
Run Code Online (Sandbox Code Playgroud)

...你写的这个:

[ "$foo" -gt "$bar" ] && [ "$foo" -lt "$qux" ]
Run Code Online (Sandbox Code Playgroud)

...关闭两个测试表达式并使用shell语法来组合它们的输出.由于[/ test是内置的shell,因此不需要将其作为外部命令执行,因此在运行test意味着调用时,这不会产生70年代的性能开销/usr/bin/test.