为什么要在POSIX sh的`test` /`[`字符串比较中附加一个额外的字符?

问题描述

在阅读Debian的/usr/bin/startx之后,我发现了一些奇特的东西:

mcookie=`/usr/bin/mcookie`

if test x"$mcookie" = x; then
    echo "Couldn't create cookie"
    exit 1
fi

我不明白为什么需要额外的x-写下面的内容等同吗?

mcookie=`/usr/bin/mcookie`

if test "$mcookie" = ""; then
    echo "Couldn't create cookie"
    exit 1
fi

我最初以为,如果sh变量未设置(这不是唯一的实例,那么mkcookie的早期版本可能会打印出一些错误(这不是唯一的实例;这些比较类型在整个过程中分散存在)剧本)。但是经过进一步思考后,它并没有多大意义,因为该变量被加了引号,并且shell会将其扩展为空字符串。

我仔细阅读了Bash手册页的Dash --posix部分,并检查了POSIX本身。在tests1 = s2 True if the strings s1 and s2 are identical; otherwise,false下,它什么也没说。我认为编写脚本的人知道他们在做什么-那么有人可以对此有所了解吗?

谢谢, 埃德温

解决方法

这是Wooledge Bash Pitfall #4的摘录:

您可能已经看到过这样的代码:

[ x"$foo" = xbar ] # Ok,but usually unnecessary.

对于必须在缺乏x"$foo"且具有更原始的[[的非常古老的shell上运行的代码,则需要[ hack,否则$foo开始时会感到困惑-。在上述较旧的系统上,[仍然不在乎=右侧的令牌是否以-开头。它只是按字面意义使用它。只是左侧需要特别注意。

请注意,需要此替代方法的外壳不符合POSIX。甚至Heirloom Bourne外壳也不需要这样做(可能是非POSIX Bourne外壳克隆,仍被广泛用作系统外壳)。这种极端的可移植性几乎不是必需的,并且会使代码的可读性(更难看)。

如果您在本世纪的代码中找到了它,那就是货真相教不断被那些不报价的人所强化。

/usr/bin/startx特别是从1993年2月起至少使用XFree86 2.1以来就使用了这个习惯用法,并且此后的任何更新都可能只匹配样式。