在内置测试中使用 -n 和 -z - Bash

在内置测试中使用 -n 和 -z - Bash

在 bash 中考虑以下内容:

root@debian-lap:/tmp I=$(echo)
root@debian-lap:/tmp echo "$I"

root@debian-lap:/tmp [ -z "$I" ] && echo "TRUE" || echo "FALSE"
TRUE

这意味着变量 $I 是zero。我可以通过否定测试来实现相同的目的,以查看变量是否非零,并使!测试反向,以便它检查变量zero

root@debian-lap:/tmp ! [ -n "$I" ] && echo "TRUE" || echo "FALSE"
TRUE
root@debian-lap:/tmp

所以,我的问题是,何时使用-zand是否有任何特殊情况! -n,反之亦然! -z-n因为它们基本上正在进行相同的测试?

谢谢

答案1

1. [ -z "$var" ]
2. [ ! -n "$var" ]
3. ! [ -n "$var" ]
4. [ ! "$var" ]
5. [ "$var" = '' ]
6. [ ! "$var" != '' ]
7. [ '' = "$var" ]...²

在 POSIX shell 中功能都是等效的。 Bourne shell 没有!关键字,因此不支持上面的 3 个,并且除了 7 之外的所有 shell 中都存在各种具有特殊值$var(如=-n!...)的错误(许多其他 shell 也有类似的错误)。

同样,您可以(并且应该)使用[ "$a" = "$b" ] && [ "$x" = "$y" ]代替[ "$a" = "$b" -a "$x" = "$y" ],后者已被弃用且不可靠。

of !3 是 POSIX shell 功能。test/实用程序对于可能想要使用它并否定条件的其他 shell 或非 shell 应用程序[支持其自己的运算符(如 2/6 中所示)仍然有意义。!

test实用程序由 Unix v7 引入。在此之前,有一个if实用程序有!, =, !=, -a/ -o,但没有-n/ -z

我想添加-n/-z是为了方便(test -n "$var"是缩写test "$var" != ''-z添加是为了保持一致性)


1 从技术上讲,虽然test/[几乎内置在所有类似 Bourne 的 shell 中,但这并不是 POSIX 强制要求的,而且早期版本的 Bourne shell 也没有内置它。虽然 Almquist shell 始终具有test内置命令,但某些 BSD 并未启用它,因此某些 BSD直到 2000 年代才内置[/ 。在任何情况下,无论特定 shell 是否内置有/命令,所有 POSIX 系统在文件系统上也会有/命令(其行为可能与系统上任何 shell 的/内置命令相同,也可能不同)。系统)。testsh[test[test[test

² 这并不是说这是唯一可用于测试变量是否为空字符串的命令。

case $var in
  "") ...
esac

是一种不涉及运行任何命令的方法。

expr "x$var" : 'x$' > /dev/null
${var:+"false"}
awk 'BEGIN{exit(ARGV[1] != "")}' "$var"
[ "${#var}" -eq 0 ]

还有更多复杂方法的例子。

一些类似 Korn 的 shellbash也有一些内置的条件和算术结构体旨在替换[命令 ( [[ -z $var ]], ((${#var} == 0))...)。

答案2

出于同样的原因,您会得到-n和,其他测试套件也会给您提供和,或者和。通过避免双重否定,一些测试用例可以让未来的维护者变得更加清晰。另外,正如上面的评论中提到的,与现代 POSIX 不同,古代的版本(即 Bourne 和 Thompson shell)没有关键字来否定表达式的真实性。-z==!=ANDNOTshsh!test

相关内容