“test -n && echo notempty”打印“notempty”。这是预期的行为吗?

“test -n && echo notempty”打印“notempty”。这是预期的行为吗?

当我执行以下行时

test -n && echo not empty

它打印“非空”。当您有一个空变量并测试非空而忘记引用该值时,就会发生这种情况:

VAR=
test -n  $VAR  && echo wrong 1
test -n "$VAR" && echo wrong 2

这是预期的行为吗?

答案1

是的,这是预期的行为。当仅将一个参数传递给 时test,将执行长度检查。从man bash

test 和 [ 使用一组基于参数数量的规则来评估条件表达式。

0 个参数:表达式为假。

1 个参数:当且仅当参数不为空时,表达式才为 true。

也就是说,本质上它相当于test foo,但用作-n字符串。

答案2

test -n初步证据格式错误,因为-n需要参数。我相信一些历史实现将其视为语法错误(并返回非零状态)。然而,在 21 世纪您可能遇到的所有 shell 中,行为都是明确定义的(通过POSIX,遵循现有惯例):如果test只有一个参数,则当且仅当该参数非空时才为真。

请注意,如果省略引号,对于 的某些非空值,测试可能最终为 false $VAR。如果 中存在通配字符,它甚至可以打印出错误消息$VAR

VAR='foo -a -z bar'; test -n $VAR || echo "true... and false is false"
VAR='= n-'; test -n $VAR || echo "this is an equality test"
VAR='*'; test -n $VAR || echo "you may or may not see this depending on what files are in the current directory"

test -z $VAR同样被打破。

Ksh、bash 和 zsh 有一个[[ … ]]模仿传统test[实用程序的条件结构。与 不同[,它要么是外部实用程序,要么是像解析一样的内置实用程序,[[ … ]]是 shell 语法的一部分。内部没有分词或通配符[[ … ]][[ -n $VAR ]]没问题(只要你不关心你的脚本不会在其他 shell 下运行,比如 ash)。

答案3

另请检查[[ ... ]],它不会出现此行为:

[[ -n $VAR ]] && echo wrong 3
[[ -n "$VAR" ]] && echo wrong 4

答案4

当您执行以下操作时似乎:

VAR=
test -n $VAR && echo helloworld

它对待它就好像争论不存在一样:

test -n && echo helloworld

并且,由于某种原因,当未提供参数时,它总是随后运行该命令(即显示 helloworld)。我在另一个一元运算符上尝试了这个,它做了同样的事情:

FILENAME=
test -f $FILENAME && echo helloworld

我认为如果你想得到预期的行为,你必须引用这个论点:

VAR=
test -n "$VAR" && echo helloworld
FILE=
test -f "$FILE" && echo helloworld

以上不会产生任何消息回显到屏幕上。

至于这是预期的行为吗?我在任何地方的文档中都找不到它,但是,它似乎相当可重复且一致。

相关内容