首选

首选

bash 中是否有区别,或者语句否定的首选用法?

if ! [[ -z "${var}" ]]; then
  do_something
fi

相对

if [[ ! -z "${var}" ]]; then
  do_something
fi

答案1

! [[ expression ]]

如果整个测试返回 false,则为 true

[[ ! expression ]]

如果单个表达式返回 false,则该值为 true。


由于测试可以是复合表达式,因此这可能非常不同。例如:

$ [[ ! 0 -eq 1 || 1 -eq 1 ]] && echo yes || echo no
yes
$ ! [[ 0 -eq 1 || 1 -eq 1 ]] && echo yes || echo no
no

就我个人而言,我更喜欢在适用的情况下在测试构造内部使用否定,但根据您的意图,在外部也完全可以。

答案2

A! cmd实际上是一个管道,并且!否定退出代码所有的管道。

来自 man bash:

管道 管道是由一个或多个命令组成的序列,由一个控制运算符 | | 分隔开。或|&。管道的格式为:

         [time [-p]] [ ! ] command [ [|||&] command2 ... ]

...
如果保留字!在管道之前,该管道的退出状态是如上所述的退出状态的逻辑非。 shell 在返回值之前等待管道中的所有命令终止。

从这个意义上来说,a:

! [[ 2 -eq 2 ]]

!是整个退出代码的否定 ( ) [[(一旦全部执行完毕)。因此,退出代码为 0:

!  [[ 2 -eq 2 && 3 -eq 4 ]]

然而

A[[ ! ]]是一个复合命令(不是管道)。来自 man bash:

复合命令
...
[[ 表达式 ]]
根据条件表达式表达式的计算结果返回 0 或 1 状态。
表达式由下面条件表达式中描述的主要元素组成。

因此,退出代码为 1:

[[ ! 2 -eq 2 && 3 -eq 4 ]]

因为这实际上相当于:

[[ ( ! 2 -eq 2 ) && ( 3 -eq 4 ) ]]

通过短路求值, 的右侧&&永远不会被求值,实际上等价于这个短得多的表达式:

[[ ! 2 -eq 2 ]]

这永远是错误的(1)。

简而言之:里面[[,!影响部分的表达式。

首选

使用!内部[[更为常见(并且可移植到更多 shell(使用)),但如果没有通过明智地使用 来明确控制来界定否定的范围(这可能会成为构造内部的问题),[有时可能会造成混乱。()[

但是(在 bash、ksh 和 zsh 中)的结果! [[定义非常明确并且更容易理解:执行整个过程[[并否定结果。

应该使用哪一个是个人喜好(和理解)的问题。

相关内容