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 中)的结果! [[
定义非常明确并且更容易理解:执行整个过程[[
并否定结果。
应该使用哪一个是个人喜好(和理解)的问题。