为什么[-n]不像[-n“”]一样假?


20

我的问题是关于此代码产生的返回值:

if [ -n ]; then echo "true"; else echo "false"; fi

打印true

它的补充测试[ -z ]还使用打印true

if [ -z ]; then echo "true"; else  echo "false"; fi

在上面的代码中,为什么[ -n ]测试会假设根本没有传递的字符串值不为null?

下面的代码打印出来false。这是预期的,因为传递的字符串值为null,长度为零。

if [ -n "" ]; then echo "true"; else  echo "false"; fi

Answers:


14

[X]相当于[ -nX]即使X与开始-提供没有操作数。

$ [ -o ] ; echo $?
0
$ [ -eq ] ; echo $?
0
$ [ -n -o ] ; echo $?
0
$ [ -n -eq ] ; echo $?
0

4
请注意,从历史上看,[ -t ]正在测试stdout是否为终端(的缩写[ -t 1 ]),并且某些shell仍在进行此操作(ksh93仅在使用纯-t文本的情况下),因此[ -n "$var" ]比使用更好[ "$var" ]。尽管在某些旧的test实现中对于$varlike 值仍然失败=,在这种情况下[ "" != "$var" ]or [ "x$var" != x ]case $x in "")...可能更好。
斯特凡Chazelas

3
-o这里有趣的选择。在像这样的shell中bash-o既是一元的(测试是否设置了选项),又是二进制的(或)运算符,所以类似[ ! -o monitor ]的东西是模棱两可的。是否正在测试该monitor选项未设置,!或者monitor是否为非空字符串?POSIX规则决定:后者(与有所不同[[ ! -o monitor ]])。
斯特凡Chazelas

30

[ -n ]不使用-n测试。

-n[ -n ]是不是在所有的测试。当[和之间只有一个参数时],该参数是一个字符串,将对其进行测试以查看其是否为空。即使该字符串具有前导-,它仍将被解释为操作数,而不是测试。由于字符串-n不是空的-它包含两个字符,-并且n不是零characters-- [ -n ]计算结果为True。

作为伊格纳西奥巴斯克斯-拉姆斯说,那里string是一个参数,该测试执行上string在相同的测试通过在其上执行。当碰巧是,没有什么特别的事情发生。的在与所述第二中是简单的字符串被测试空虚。[ string ][ -n string ]string-n-n[ -n ]-n[ -n -n ]

[和之间只有一个参数时],该参数始终是要测试其是否为非空的字符串,即使该名称恰好与测试相同。同样,当和之间有两个参数[]并且第一个参数-n为时,第二个参数始终是要测试其是否为非空的字符串,即使该名称恰好与测试名称相同。这仅仅是因为的语法[坚持要求,在[和之间]或之后的单个参数-n是字符串操作数。

由于[ -n ]不使用-n测试的原因,因此[ -z ]不使用-z测试。


您可以了解更多关于[bash通过检查它的帮助。注意,这是一个内置的shell

$ type [
[ is a shell builtin

因此,您可以运行help [以获取帮助:

$ help [
[: [ arg... ]
    Evaluate conditional expression.

    This is a synonym for the "test" builtin, but the last argument must
    be a literal `]', to match the opening `['.

有关更多信息,包括支持哪些测试以及它们如何工作,您将必须在上查看帮助test。运行命令时help test,将获得详细列表。而不是全部复制,这是关于字符串运算符的部分:

      -z STRING      True if string is empty.

      -n STRING
         STRING      True if string is not empty.

      STRING1 = STRING2
                     True if the strings are equal.
      STRING1 != STRING2
                     True if the strings are not equal.
      STRING1 < STRING2
                     True if STRING1 sorts before STRING2 lexicographically.
      STRING1 > STRING2
                     True if STRING1 sorts after STRING2 lexicographically.

注意,-n STRING并且STRING做同样的事情:它们测试字符串STRING是否为空。


2
很好的解释
Sergiy Kolodyazhnyy

1
也许还提到这对未设置的未引用变量有影响,例如:paste.ubuntu.com/25831047
Sergiy Kolodyazhnyy 17-10-27

1
@SergiyKolodyazhnyy我认为单独回答可能会更好。未设置或设置但为空或仅包含IFS空格的变量将执行此操作;包含多个单词而不是零的变量会产生另一种效果,并可能导致运行完全不同的测试。仅作为操作数的字面意义上出现的字符串只有在不包含空格或制表符或使用引号的情况下才能正常工作。如果我以一种易于访问的方式涵盖此主题,答案将变得更长且更加复杂。如果您决定发布答案,请随时在这里@我!
伊莱亚·卡根

@Eliah Kagan,尽管Ignacio Vazquez-Abrams的回答回答了我的问题,但您的回答更加完整和详细。
拉维·库玛

1
我认为您已经错过了它的原因,并且必须这样:如果不这样,[ "$var" ]将永远无法用作测试,因为$var可能会扩展到-n
R.,

12

[ -n ]之所以如此,是因为[命令(又名test命令)根据给定的参数数量起作用。如果仅给定单个参数,则参数为非空字符串时,结果为“ true”。“ -n”是一个包含2个字符的字符串,不能为空,因此为“ true”。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.