为什么是[[!!expr]]等价于[[!expr]]在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用任何真表达式替换,并用任何假表达式否定,它似乎会做同样的事情。
回答
[[是一种扩展语法,它提供(主要)一个[. 那么,要了解它的行为,应该从[.
POSIXtest规范描述了[预期的行为方式。在一个地方,它确实提供了符合此问题中描述的期望的描述:
! expression- 如果表达式为假,则为真。如果表达式为真,则为假。
...但后来,关于如何根据原语数量进行解析的更详细描述与此预期相矛盾:
- 0 个参数:退出假 (1)。
- 1 个参数:如果 $1 不为空,则退出真 (0);否则,退出假。
- 2 个参数:如果 $1 是
!,如果 $2 为空则退出真,如果 $2 不为空则为假。
如果 $1 是一元主,如果一元测试为真,则退出真,如果一元测试为假,则为假。否则,会产生未指定的结果。- 3 个参数:如果 $2 是二进制主,则执行 $1 和 $3 的二进制测试。
如果 $1 是 '!',则否定 $2 和 $3 的两个参数测试。
(过时的 XSI 行为:如果 $1 是 '(' 并且 $3 是 ')',则执行 $2 的一元测试。在不支持 XSI 选项的系统上,如果 $1 是 '(' 并且 $3 是 ',则结果未指定)'。否则,会产生未指定的结果。- 4 个参数:如果 $1 是 '!',则否定 $2、$3 和 $4 的三参数测试。
(过时的 XSI 行为:如果 $1 是 '(' 并且 $4 是 ')',则执行 $2 和 $3 的双参数测试。)在不支持 XSI 选项的系统上,如果 $1 是 '(' $4 是')'。否则,结果是不确定的。- 超过 4 个参数:结果未指定。
在 的情况下! ! 1 -eq 1,您有一个五参数的情况。结果是 unspecified,因为标准没有指定如果第一个参数是 ,则五参数 case 是四参数 case 的否定!。
正如 Zilog80 所建议的:如果您不想受到这些限制,请考虑将您的测试语法! 排除在外;! [[ ... ]]发生在 shell 命令解析层而不是定制的测试语法特定逻辑中,并且! ! [[ ... ]]在那里完全有效。
- @oguzismail, ...I wonder if we're talking past each other. The point I'm making is only that the behavior is unspecified, which means the shell is _under no obligation_ to make that flag a toggle vs something that gets set and stays set; it's just as correct for it to keep its current implementation as it would be to have a toggle-based one that behaves the way the OP expects. (Of course, being unspecified also means it could switch to doing it the other way in a new release without breaking any guarantees... but then, it could also switch back).