为什么是 [[ ! ! expr ]] 等价于 [[ ! expr ]] 在 bash 中?

Why is [[ ! ! expr ]] equivalent to [[ ! expr ]] in bash?

在 bash 中,我不明白为什么第三条命令不正确:

[[ 1 -eq 1 ]]         # $? is 0
[[ ! 1 -eq 1 ]]       # $? is 1
[[ ! ! 1 -eq 1 ]]     # $? is 1 (??)
[[ ! ( ! 1 -eq 1 ) ]] # $? is 0

如果我用任何真表达式替换 1 -eq 1 并用任何假表达式取反,它似乎会做同样的事情。

[[ 是一种扩展语法,它(主要)提供了 [ 的超集。那么,要了解其行为,应该从 [.

的标准开始

The POSIX test specification 描述了 [ 的预期行为。在一个地方,它确实提供了符合这个问题描述的期望的描述:

! expression - True if expression is false. False if expression is true.

...但是稍后,关于如何根据基元数量进行解析的更详细描述与此预期相矛盾:

  • 0 arguments: Exit false (1).
  • 1 argument: Exit true (0) if is not null; otherwise, exit false.
  • 2 arguments: If is !, exit true if is null, false if is not null. If is a unary primary, exit true if the unary test is true, false if the unary test is false. Otherwise, produce unspecified results.
  • 3 arguments: If is a binary primary, perform the binary test of and . If is '!', negate the two-argument test of and . (Obsolescent XSI behavior: If is '(' and is ')', perform the unary test of .. On systems that do not support the XSI option, the results are unspecified if is '(' and is ')'. Otherwise, produce unspecified results.
  • 4 arguments: If is '!', negate the three-argument test of , , and . (Obsolescent XSI behavior: If is '(' and is ')', perform the two-argument test of and .) On systems that do not support the XSI option, the results are unspecified if is '(' and is ')'. Otherwise, the results are unspecified.
  • More than 4 arguments: The results are unspecified.

! ! 1 -eq 1 的情况下,您有一个五个参数的情况。 结果未指定,因为标准未指定如果第一个参数是 !.[=25,则五参数情况是四参数情况的否定=]


正如 Zilog80 所建议的:如果您不想受到这些限制,请考虑将您的 ! 放在 测试语法之外; ! [[ ... ]] 发生在 shell 命令解析层,而不是在定制的测试语法特定逻辑中,并且 ! ! [[ ... ]] 在那里完全有效。

在解析 ! 时,bash 为以下表达式设置一个标志,告诉它反转其结果。因此,解析两个或多个 ! 等同于解析单个 !。我提出 patch 来解决这个问题,它被接受了。