为啥&&和||优先于 -a 和 -o
Posted
技术标签:
【中文标题】为啥&&和||优先于 -a 和 -o【英文标题】:Why are && and || preferred to -a and -o为什么&&和||优先于 -a 和 -o 【发布时间】:2016-04-17 18:41:08 【问题描述】:在 bash 中编写 if
块时,shellcheck 告诉我 &&
和 ||
优于使用 -a
和 -o
。
为什么?它更快,或者只是为了让脚本看起来更干净的风格偏好?
我得到的具体信息是:
^-- SC2166: Prefer [ p ] || [ q ] as [ p -o q ] is not well defined.
【问题讨论】:
如果 shellcheck 报告了问题,它会在问题旁边打印一个链接到描述。 @hek2mgl 我使用的是本地版本,它只给了我一个问题代码,但我没有找到任何有用的代码来寻找该代码 @MatthewHerbst 检查这个:github.com/koalaman/shellcheck/wiki/SC2166 @hek2mgl 不知道为什么我找不到,谢谢! 【参考方案1】:来自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
。
【讨论】:
那么,就我对POSIX的基本了解而言,这基本上意味着代码&&
和||
与其他可能没有扩展POSIX的机器更兼容?
@MatthewHerbst,这不仅仅是它是否扩展的问题——POSIX 规范本身并没有描述-a
和-o
需要如何为所有 POSIX 提供足够详细的行为-兼容的实现在模棱两可的情况下表现得完全相同。
请注意[
的结果会在第一次评估后影响$PIPESTATUS
数组。使用内部的 [[
就像在 if [[ "$PIPESTATUS[0]" -ne 0 && "$PIPESTATUS[1]" -ne 0 ]]; then...
中一样,至少对于 Bash。以上是关于为啥&&和||优先于 -a 和 -o的主要内容,如果未能解决你的问题,请参考以下文章