shell逻辑非

shell逻辑非

两者之间更喜欢什么

if ! [ ... ]; then

if [ ! ... ]; then

实际上它们的结果相同,有首选语法吗?在前一种语法中,评估的 not 是 shell 内置的,而在后一种语法中, not 是内置的test,这有什么区别吗?

答案1

可移植性的考虑。

关键字!是 POSIX 但不是 Bourne,而/命令从一开始!就支持。[test

所以[ ! ... ]! [ ... ].

否则,只要您不使用已弃用的运算符-o-a二元运算符,它们就应该是等效的(如果我们抛开某些旧test/[实现中的解析错误)。

实际上,在 Bourne shell 中,要做

if ! cmd1; then
  cmd2
fi

你必须这样做:

if cmd1; then
  :
else
  cmd2
fi

(或使用cmd1 || cmd2,尽管这最终可能会导致不同的退出状态)。

set -o errexit//与set -e陷阱交互ERR

if在/语句的条件部分之外fi,正如 @mosvy 所指出的,[ ! ... ]和之间的另一个区别是,后者在返回 false 且选项打开! [ ... ]时不会导致 shell 退出。! [ ... ]errexit

!应用于任何管道会取消 的效果,errexit因为 shell 认为管道的退出状态被用作状况。这同样适用于failing-pipeline || cmdfailing-pipeline && cmd...

而 with [ ! ... ],!只是传递给[命令的常规参数,最终就 shell 而言errexit,它只是[返回成功或失败退出状态的命令。

$ sh -ec '[ ! a = a ]; echo here'; echo "$?"
1
$ sh -ec '! [ a = a ]; echo here'; echo "$?"
here
0

if当这些命令作为//while语句的条件部分运行时until,这不适用,如其中所示,errexit不适用。

这同样适用于ERR类似 Korn 的贝壳的陷阱:

$ ksh -c 'trap "echo OUCH" ERR; ! [ a = a ]'
$ ksh -c 'trap "echo OUCH" ERR; [ ! a = a ]'
OUCH

在实践中,这可能不会产生影响,因为[几乎总是用作条件,而 whereerrexit不适用(无论是在if/ while/until语句中还是后跟&&/ ||)。

答案2

[ … ]等于test …,所以! [ … ]等于! test …。这意味着,您否定命令的结果test。在本例中,!是一个 shell 命令。

来自info bash,例如在“管道”部分:

如果保留字‘!’在管道之前,退出状态是上述退出状态的逻辑非。

另一方面,[ ! … ]意味着test ! …。这意味着,您否定测试中的表达式。参见:!man test

   ! EXPRESSION
          EXPRESSION is false

所以它可以有不同的含义。如果您有复杂的表达式,则否定可能仅适用于一部分。

这取决于你,你喜欢什么。

相关内容