String 用X“测试空字符串&引用;

String 用X“测试空字符串&引用;,string,bash,shell,posix,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)?准备好上历史/便携课程了 关于服务器故障,也有人问了同样的问题,但没有人解释为什么您会看到带有X”“东西的代码。啊,这

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

if [[ -z $myvar ]]; then do_stuff; fi
但是我看到很多代码是这样写的:

if [[ X"" = X"$myvar" ]]; then do_stuff; fi
这种方法更便于携带吗?这只是
-z
之前的历史积垢吗?它是用于POSIX Shell的吗(尽管我在脚本中看到它被用于
bash
)?准备好上历史/便携课程了



关于服务器故障,也有人问了同样的问题,但没有人解释为什么您会看到带有
X”“
东西的代码。

啊,这是我首选的问题和答案之一,因为我只是想了想才得出答案。设置
X
,以防字符串以
-
开头,该字符串可作为测试的标志。在前面放置一个
X
,只会删除该情况,并且比较仍然可以保持


我也喜欢这一点,因为这种技巧几乎是从过去最古老的计算时代继承下来的,当你试图阅读一些最可移植的shell脚本(autoconf、configure等)时,你会遇到它。基本上,因为在很久以前,
test
的行为更为复杂,并且在不同的系统中没有统一定义(因此必须仔细编写可移植代码,以避免不可移植的构造)

特别是,在
test
是一个内置的shell之前,它是一个单独的可执行文件(请注意,MacOS X仍然将
/bin/test
/bin/[/code>作为可执行文件)

if [ -z $variable ]
$variable
为空时,将通过其别名
[
使用3个参数调用测试程序:

argv[0] = "["
argv[1] = "-z"
argv[2] = "]"
因为变量为空,所以没有可扩展的内容。因此,编写代码的安全方法是:

if [ -z "$variable" ]
它工作可靠,将4个参数传递给
测试
可执行文件。诚然,几十年来,测试程序一直是大多数shell的内置程序,但旧设备很难使用,很久以前学习的良好实践也是如此

由X前缀解决的另一个问题是,如果变量包括引导破折号,或者包含相等或其他比较器,那么会发生什么。 这是一个带有散乱(错误)参数的空字符串测试,还是一个带有非数字第一个参数的数字相等测试?大约在1990年POSIX标准化行为之前,不同的系统提供了不同的答案。因此,安全的处理方法是:

if [ "X$x" = "X0" ]
或者(根据我的经验,不太常见,但完全等效):


这是所有像这样的边缘案例,与测试是一个单独的可执行文件的可能性有关,这意味着便携式shell代码仍然比现代shell实际需要的更多地使用双引号,并且使用X前缀符号来确保事情不会被误解。

有意义……但是,必须是hi因为
myvar=“-somval”如果[-z$myvar];那么echo“zero”;fi
不会在我的shell(bash)上输出“zero”(或者呕吐)…@mitch:是的,它可能不会在
-z
上完全失败,但是它被用作(我可能认为是出于自定义)所有字符串比较的标记。我测试过的
test
的所有版本(bash内置)正确解析命令,如
[-z=-z]
[]!=[]
,等等。大多数,也许所有的类Unix系统仍然有“test”和“[”可执行文件(在Ubuntu上,它们在/usr/bin中,而不是在/bin中)。这允许它们从shell脚本以外的东西中使用。(请参阅您的系统文档;该命令的行为可能与内置的shell略有不同,而内置的shell本身在不同的shell之间可能会有所不同。)顺便说一句,这篇文章给出了一个很好的答案
if [ "X$x" = "X0" ]
if [ X"$x" = X"0" ]