当我执行以下行时
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
以上不会产生任何消息回显到屏幕上。
至于这是预期的行为吗?我在任何地方的文档中都找不到它,但是,它似乎相当可重复且一致。