有关答案的旧版本,请参阅此答案的第二部分。如果您想了解详细信息,请继续阅读
问题原因
在问题本身中,据报道OP看到了too many arguments error
,但在进行测试时bash
似乎并非如此:
$ [ $1 != '' ] && [ $2 != '' ]
bash: [: !=: unary operator expected
随着/bin/sh
这实际上被链接到/bin/dash
Ubuntu上,错误报告如下:
$ sh
$ [ $1 != '' ] && [ $2 != '' ]
sh: 1: [: !=: unexpected operator
独立版本/bin/test
还可以:
$ /usr/bin/test $1 != ''
/usr/bin/test: missing argument after ‘’
旁注:如果您想知道什么是什么/usr/bin/test
以及为什么要使用bash
and sh
,那么您应该知道这[
是test
命令的别名,它也作为独立的可执行文件或更常见地存在-作为shell内置的,这是每个shell会首先使用的东西。至于if
语句,它们在命令的退出状态下操作,因此为什么[
和test
是命令,其他所有内容都是该命令的参数-命令行参数的不正确顺序会导致错误。
返回主题:尚不清楚OP如何获得不相关的错误。但是,在所有3种情况下,问题都是相同的-未设置的变量将被视为空,因此,使用这些未引用的变量,shell看到的是
[ != '' ]
破坏了test
理解的语法。还记得我所说的关于命令行参数顺序错误的说法吗?因此,为什么报价很重要。让我们启用诊断输出并查看shell执行的内容:
$ set -x
# throws error
$ [ $1 != '' ] && [ $2 != '' ]
+ '[' '!=' '' ']'
bash: [: !=: unary operator expected
# no error
$ [ "$1" != '' ] && [ "$2" != '' ] || echo null vars
+ '[' '' '!=' '' ']'
+ echo null vars
null vars
测试未设置变量的更好方法
您经常看到的一种方法是:
if [ "x$var1" == "x" ] && [ "x$var2" == "x" ];
then
echo "both variables are null"
fi
引用吉尔斯:
在[“ x $ 1” =“ x”]中,x前缀确保x“ $ 1”看起来不可能像运算符,因此shell解析此测试的唯一方法是将=视为二进制运算符。
大概应该是可移植的,因为我已经在/bin/sh
脚本中看到了。它也可以像
if [ "x${var1}${var2}" == "x" ]; then
...
fi
当然可以使用-z
标志,但是根据对某些shell的研究,特别是ksh88(根据Stephane Chazelas的说法),该标志是有缺陷的。
也可以看看