在bash中,test命令、[命令、[[命令都可以用来做一些判断。例如,这三个命令都可以用来判断一个字符串是否为空。在实际使用中,这些命令的使用有一些异同,也有一些注意事项。详情如下。test命令和[命令的关系在bash中,[关键字本身就是一个命令,它不是if命令的一部分。执行help[命令,其指令如下:[:[arg...]计算条件表达式。这是内置“test”的同义词,但最后一个参数必须是文字],以匹配开头的[。即[命令是test命令的同义词,其条件表达式的判断结果与test命令完全相同。但是[命令要求命令的最后一个参数必须是]],好像是关闭方括号的效果。在实际使用中,test命令和[命令经常与if命令和while命令结合使用。但它不一定是。test命令和[命令本身是独立的命令,可以独立执行。后面会用test命令来说明它的用法。这些说明都适用于[命令。注意:]本身不是bash命令,它只是[命令需要的一个参数,而且必须是最后一个参数。注意:使用[命令时,最大的错误是没有在该命令后加空格。例如,[string1!=string2]是错误的。永远注意[本身是一个命令,命令名称是[。这条命令后面会有一些参数,命令名和参数要用空格隔开。[string1这种写法实际上会执行名为[string1的命令,而不是[命令。同样,]本身就是一个参数,也需要用空格来分隔其他参数。string2]实际上是一个名为“string2]”的参数。而不是string2和]两个参数。使用测试命令判断字符串是否为空,执行帮助测试命令,如下:test:test[expr]计算条件表达式。退出状态为0(真)或1(假),具体取决于EXPR的评估。测试的行为取决于参数的数量。阅读bash手册页以获得完整的规范。字符串运算符:-zSTRING如果字符串为空则为真。-nSTRINGSTRING如果字符串不为空则为真。即测试命令使用-zSTRING运算符来判断STRING字符串的长度是否为0,如果为0则空字符串返回true。具体写法是test-zSTRING,[命令写成[-zSTRING]。-nSTRING运算符判断STRING字符串的长度是否为0,如果不为0则不是空字符串,返回true。具体写法是test-nSTRING,[命令写成[-nSTRING]。-n运算符可以省略,直接写成testSTRING,或[STRING]。注意:在实际使用中要注意以下几点:判断变量值对应的字符串是否为空时,必须用双引号将变量值括起来。否则,当变量值为空或包含空格时,将返回异常结果。比如写test-n"$string",不建议写test-n$string。bash取0为真,1为假。上述测试命令的说明也是如此。在大多数编程语言中,1为真,0为假。注意区分,避免弄错判断条件的执行关系。上面helptest的描述中提到了test命令的参数个数会影响它的行为。具体可以参考manbash的说明。不同数量的参数会导致测试命令返回许多意想不到的结果。下面以一个empty_string.sh脚本来说明使用test命令和[命令判断字符串是否为空的方法。内容如下:#!/bin/bashfunctionempty_string(){iftest-n$1;然后echo'(1)-n$1:'“没有引号:不是空的。”fi如果[-z$1];然后echo'(2)-z$1:'“无引号:空。”fiiftest-n"$1";然后echo'(3)-n"$1":'"Quote:notempty."fi如果[-z"$1"];然后echo'(4)-z"$1":'"Quote:empty."fi}empty_string脚本“$1”使用测试命令的-n和-z运算符来判断传入脚本的第一个参数是否为空字符串,比较用双引号括起变量值的测试结果和没有双引号。具体执行结果如下:$./empty_string.shgo(1)-n$1:Noquote:notempty.(3)-n"$1":Quote:notempty.$./empty_string.sh"go在”。/empty_string.sh:第5行:测试:go:预期二元运算符。/empty_string.sh:第9行:[:go:预期二元运算符(3)-n“$1”:引用:不为空。$./empty_string。sh(1)-n$1:无引号:非空。(2)-z$1:无引号:空。(4)-z"$1":引号:空。可以看到,执行./empty_string.shgo命令,传入的第一个参数的值不包含空格,$1变量值带双引号和不带双引号的判断结果都是正确的。执行./empty_string.sh"goon"命令,传入的第一个参数值包含空格。不带双引号的$1变量值在执行语句时会报错,提示“binaryoperatorexpected”。测试命令在-n、-z运算符之后只需要一个参数。这里test-n$1扩展为test-n测试字符串。-n后面提供了两个参数,加上-n一共是三个参数,导致执行出错。使用双引号将$1变量的值括起来,整个变量值将被视为一个参数。执行test-n"$1"命令不会报错。在不提供第一个参数的情况下执行./empty_string.sh命令,测试结果比较奇怪。-n$1考虑$1不为空。-z$1认为$1为空。只有-z"$1"正确判断第一个参数值为空。原因是当没有提供第一个参数时,这里$1的值为空,相当于没有。test-n$1语句经过bash处理后,结果为test-n。[-z$1]语句经过bash处理后,结果为[-z],相当于test-z。test-n和test-z都返回true。所以才会打印出$1既为空又不为空,判断结果不符合预期。再次可以看到,-z"$1"将变量值用双引号括起来,得到了预期的判断结果。加上双引号可以避免很多不正常的现象。使用bash-x./empty_string.sh在执行脚本时打印调试信息,可以看到[-z$1]和[-z"$1"]展开结果的区别:$bash-x./empty_string.sh+empty_string''+test-n+echo'(1)-n$1:''无引号:非空。'(1)-n$1:无引号:非空。+'['-z']'+echo'(2)-z$1:''无引号:空。'(2)-z$1:无引号:空。+test-n''+'['-z''']'+echo'(4)-z"$1":''引用:空。'(4)-z"$1":引用:空。结合上面的代码可以看到,通过[-z$1]扩展得到的调试信息是'['-z']',-z后面没有任何参数。并且[-z"$1"]扩展为'['-z''']'。-z后面有一个参数'',这个参数的值为空字符串。使用[[命令判断字符串是否为空,见帮助[[[[命令说明如下:[[...]]:[[表达式]]执行条件命令。根据条件表达式EXPRESSION的评估,返回状态0或1。表达式由内置的“test”所使用的相同原色组成,并且可以使用以下运算符组合:(EXPRESSION)返回EXPRESSION的值!如果EXPRESSION为假,则EXPRESSION为真;elsefalse&EXPR2如果EXPRESSIONEXPR1和EXPR2都为真;否则假EXPR1||EXPR2如果EXPR1或EXPR2为真则为真;elsefalse即[[命令可以使用test命令支持的条件表达式进行判断。下面详细说明它们之间的一些区别。上面说过,[命令要求最后一个参数必须是],而]本身不是命令。同样,[[命令也需要与]]同时出现。但是]]本身也是一个命令,而不是一个参数。所以[[expression]]被称为复合命令。如下例所示:$]]:commandnotfound$]]-bash:syntaxerrornearunexpectedtoken`]]'可以看到在尝试执行]命令时,提示找不到命令,表明没有这样的命令。执行]]命令时,没有提示找不到命令,只有语法错误,预计命令前必须有[[命令。由于[[和]]都是命令,需要和其他参数用空格隔开。检查manbash中的[[是否有以下说明:不对[[和]]之间的词进行分词和路径名扩展;执行波浪号扩展、参数和变量扩展、算术扩展、命令替换、进程替换和引用删除。即当变量值在[[和]]中被引用时,不会对变量值进行分词(Wordsplitting)。即使变量值有空格,如果不加双引号也不会被分割成多个参数。test命令和[命令会进行分词,可能会导致参数个数发生变化。可以参考前面例子的描述。使用[[判断字符串是否为空的一些例子如下:$value=$[[-n$value]];echo$?1$[[-z$value]];echo$?0$value="goon"$[[-n$value]];echo$?0$[[-n继续]];echo$?-bash:syntaxerrorinconditionalexpression-bash:syntaxerrornear'on'canbeseenTo,setthevaluevariablevaluetoempty,[[-n$value]]返回1,确认变量值为不空是假的。[[-z$value]]返回0,确认变量值为空为真。即使$value没有用双引号括起来,也能正确判断。如果使用[命令,则会判断异常。当value变量的值包含空格时,[[-n$value]]可以判断正确,但是如果直接写成[[-ngoon]],就会报错。
