使用X“”对空字符串进行Bash测试

时间:2011-07-27 23:50:33

标签: string bash shell posix

我知道我可以使用-z测试Bash中的空字符串,如下所示:

if [[ -z $myvar ]]; then do_stuff; fi

但我看到很多代码写得像:

if [[ X"" = X"$myvar" ]]; then do_stuff; fi

这种方法更便携吗?这只是-z之前的历史残余吗?它适用于POSIX shell(尽管我已经看到它用于定位bash的脚本中)?准备好我的历史/便携性课程。


同样的问题在服务器故障上被称为How to determine if a bash variable is empty?,但是没有人提供关于为什么您看到带有X""内容的代码的解释。

2 个答案:

答案 0 :(得分:116)

从根本上说,因为在很久以前的时间里,test的行为更复杂,并且在不同的系统中没有统一定义(因此必须仔细编写可移植代码以避免不可移植的构造)。

特别是,在test是内置shell之前,它是一个单独的可执行文件(请注意,MacOS X仍然有/bin/test/bin/[作为可执行文件)。在这种情况下,写下:

if [ -z $variable ]

$variable为空时,将通过带有3个参数的别名[调用测试程序:

argv[0] = "["
argv[1] = "-z"
argv[2] = "]"

因为变量是空的所以没有任何东西可以扩展。因此,编写代码的安全方法是:

if [ -z "$variable" ]

这可靠地工作,将4个参数传递给test可执行文件。几十年来,测试程序已经成为大多数炮弹的内置物,但旧设备很难消失,所以很久以前就会学到很好的实践。

X前缀解决的另一个问题是,如果变量包含前导破折号,或包含等号或其他比较符,则会发生这种情况。考虑(一个不是绝对好的例子):

x="-z"
if [ $x -eq 0 ]

这是一个带有迷路(错误)参数的空字符串测试,还是带有非数字第一个参数的数字相等测试?在POSIX标准化行为之前,不同的系统提供了不同的答案,大约在1990年。因此,处理这个问题的安全方法是:

if [ "X$x" = "X0" ]

或(通常情况下,根据我的经验,但完全相同):

if [ X"$x" = X"0" ]

这是所有类似的边缘情况,与测试是一个单独的可执行文件的可能性捆绑在一起,这意味着可移植shell代码仍然比现代shell实际需要更多地使用双引号,以及X前缀表示法用来确保事情不会被误解。

答案 1 :(得分:11)

啊,这是我喜欢的问题和答案之一,因为我想出了答案。如果字符串以X开头,则设置-,可以将其作为测试的标志。在之前放置X只会删除该情况,并且比较仍然可以保留。

我也喜欢这个,因为这种技巧几乎是过去,最古老的计算时代的继承,当你尝试阅读一些最便携的shell脚本时会遇到它(autoconf,configure等)。 )