在测试命令之前/之后否定之间有区别吗?

Jam*_* Ko 11 unix linux bash shell terminal

我已经使用Bash脚本了一段时间,我想知道这两种形式的否定与test命令之间是否有任何区别:

if [ ! condition ]; then
fi

if ! [ condition ]; then
fi
Run Code Online (Sandbox Code Playgroud)

第一个告诉shell传递参数! condition进行测试,让程序自己处理否定.另一方面,第二个传递condition给测试并让shell本身否定错误代码.

在这两种形式之间进行选择时,我应该注意哪些陷阱?什么样的价值$condition可以使他们之间的结果不同?

(我似乎记得刚刚在讨论这篇文章时读过一篇文章,但我不记得如何找到它/正是所讨论的内容.)

mkl*_*nt0 8

chepner对这个问题的深刻见解为基础:

  • 在内[ ! condition ],!它只是内置函数一个参数[(内置函数的有效别名test); 它恰好[/ test将参数解释!为否定.

  • ! [ condition ],!一个shell关键字,它取消了它所遵循的任何命令([在这种情况下恰好是这样).

! [ condition ]语法隐含给你的一件事是,否定适用于作为一个整体的任何[ condition ]评估,所以如果这是意图,你不必担心运算符优先级.

在性能方面,您选择哪种语法可能并没有太大的区别; 快速测试表明:

  • 如果condition在两种情况下字面上都相同,!那么将参数[作为参数传递的速度可以忽略不计.

  • 如果!用作关键字,并且因此您可以通过不担心优先级来简化条件,则可能稍微更快(例如,! [ 0 -o 1 ]相对[ ! \( 0 -o 1 \) ];注意POSIX规范.不鼓励使用-a-o由于模糊性).

也就是说,如果我们讨论的是Bash,那么你应该考虑使用[[而不是[,因为[[是一个shell关键字,它在一个特殊的上下文中解析所包含的表达式:

  • 提供更多功能
  • 允许您安全地将表达式与&&和组合||
  • 带来更少的惊喜
  • 也略快一点(虽然这在实践中很少发生)

看到我的这个答案.