if test "x$SHELL_VAR" = "xyes"; then
...
这种方法相对于仅检查值有什么优点?
if test $SHELL_VAR = "yes"; then
...
我想这种情况肯定有原因,但我无法想出是什么原因。
如果您使用的是进行简单替换的shell且SHELL_VAR
变量不存在(或为空),则需要注意边界情况。将会发生以下翻译:
如果你使用的是进行简单替换的shell,以及SHELL_VAR
变量不存在(或为空),那么你需要小心处理边缘情况。以下翻译将会发生:
if test $SHELL_VAR = yes; then --> if test = yes; then
if test x$SHELL_VAR = xyes; then --> if test x = xyes; then
这两者中,第一个会因为缺失test
的第一个参数而产生错误。第二个则没有这个问题。
你的情况可以翻译如下:
if test "x$SHELL_VAR" = "xyes"; then --> if test "x" = "xyes"; then
至少对于符合POSIX标准的shell而言,x
实际上是多余的,因为引号确保空参数和包含空格的参数都被解释为单个对象。
test "$SHELL_VAR" = yes
,而不是使用 xyes
。对于选项处理,将顺序改为 'abc'="$1"
可能是另一个选项。 - Ciro Santilli OurBigBook.comtest
函数的第一个参数会缺失而不是成为空字符串?不同的shell处理方式有所不同吗? - phkexport xxx=''
,if test $xxx = 1 ; then echo 2 ; fi
,export xxx='yyy'
,if test $xxx = 1 ; then echo 2 ; fi
。第一个if
会出错,第二个不会。这是在bash
中。 - paxdiablo""
视为一个空参数。因此,即使VAR
为空,test "$VAR" = foo
在它们中也是安全的。 - SnakEx
。 - paxdiablo其他人尚未提到的另一个原因与选项处理有关。 如果您编写:
if [ "$1" = "abc" ]; then ...
如果 $1 的值是 '-n',则 test 命令的语法是不明确的,无法确定您正在测试什么。在前面加上 'x' 可以防止出现引导破折号的问题。
你必须查看真正古老的shell才能找到一个没有支持 -n
或 -z
的测试命令;Version 7 (1978) 的 test
命令包括它们。虽然这并不完全无关紧要——一些 Version 6 UNIX 的东西逃脱到了 BSD,但是现在,你很难在当前使用中找到任何古老的东西。
不在值周围使用双引号是危险的,就像其他一些人指出的那样。实际上,如果有可能文件名可能包含空格(MacOS X 和 Windows 都在某种程度上鼓励这种做法,而 Unix 一直支持它,尽管像 xargs 这样的工具使它变得更困难),那么每次使用文件名时都应该将其用双引号括起来。除非你负责该值(例如,在处理选项时,你在启动时将变量设置为“no”,当在命令行中包含标志时将其设置为“yes”) ,否则在证明它们安全之前不安全使用未引用的变量形式——对于许多目的,您可能也可以随时这样做。或者记录下来,如果用户试图处理具有空格名称的文件,您的脚本将会严重失败。(还有其他需要担心的字符——例如,反引号也可能非常令人讨厌。)
test
的复杂核心 [ ... ] 而不是在 shell 级别使用多个 [ test1 ] || [ test2 ] (正如 @Jay 所提到的)。 - user1556814test
的实现会做出奇怪的事情,而这种技巧可以防止这些奇怪的实现。现在您可能很幸运,不必担心这个问题。 - Jonathan Leffler我知道这个约定的原因有两个:
http://tldp.org/LDP/abs/html/comparison-ops.html
在复合测试中,即使引用字符串变量,可能也不足以满足要求。如果 $string 为空,则 [ -n "$string" -o "$a" = "$b" ] 可能会在某些 Bash 版本中出现错误。安全的方法是在可能为空的变量后面添加额外的字符,如 [ "x$string" != x -o "x$a" = "x$b" ] ("x's" 相互抵消)。
第二点,在除 Bash 外的其他 shell 中,特别是旧版本的 shell 中,测试空变量条件的选项如“-z”不存在,因此,以下语句可能会失败:
if [ -z "$SOME_VAR" ]; then
echo "this variable is not defined"
fi
如果你的目标是要在各种UNIX环境中实现可移植性,而你不能确定默认shell是否为Bash以及它是否支持-z测试条件,那么在BASH中将可以很好地工作,但更安全的做法是使用if [ "x$SOME_VAR" = "x" ]这种形式,因为它始终具有预期的效果。本质上,这是一种查找空变量的旧Shell脚本技巧,尽管现在有更清晰的方法可用,但由于向后兼容性仍在使用。
[ -n "$string" ] || [ "$a" = "$b" ]
。 - Weijun Zhouif test "yes" = "$SHELL_VAR"; then
由于它去除了丑陋的x
,并且仍然解决了https://dev59.com/jXVC5IYBdhLWcg3w0EsD#174288中提到的问题,即$SHELL_VAR
可能以-
开头并被读取为选项。
我相信这是由于
与IT技术有关。SHELLVAR=$(true)
if test $SHELLVAR = "yes" ; then echo "yep" ; fi
# bash: test: =: unary operator expected
if test $UNDEFINEDED = "yes" ; then echo "yep" ; fi
# bash: test: =: unary operator expected
SHELLVAR=" hello"
if test $SHELLVAR = "hello" ; then echo "yep" ; fi
# yep
SHELLVAR=" hello"
if test "$SHELLVAR" = "hello" ; then echo "yep" ; fi
#<no output>
但是当它在其他地方报错时,很难确定它在抱怨什么,我猜测。所以
SHELLVAR=" hello"
if test "x$SHELLVAR" = "xhello" ; then echo "yep" ; fi
这样做可以起到同样的效果,但更容易调试。
以前在DOS中,当SHELL_VAR可能未定义时,我会这样做。
如果你不使用"x$SHELL_VAR"的方式,那么如果$SHELL_VAR未定义,你会得到一个关于"="不是单目运算符或类似的错误。
x$FOO
也无法解决。 - Charles Duffy
X""
在 Bash 中测试空字符串。该问题实际上也是此问题的重复,或涵盖了大部分相同的内容。这两个重复问题都有一些很好的答案。 - Jonathan Leffler