为什么shell脚本比较经常使用x$VAR = xyes?
我经常在使用自动工具(autoconf、automake)的项目的构建脚本中看到这种情况。 当有人想要检查 shell 变量的值时,他们经常使用这个习惯用法:
if test "x$SHELL_VAR" = "xyes"; then
...
与简单地检查这样的值相比,这样做有什么好处:
if test $SHELL_VAR = "yes"; then
...
我认为我经常看到这个值肯定有某种原因,但我不能'不知道它是什么。
I see this often in the build scripts of projects that use autotools (autoconf, automake). When somebody wants to check the value of a shell variable, they frequently use this idiom:
if test "x$SHELL_VAR" = "xyes"; then
...
What is the advantage to this over simply checking the value like this:
if test $SHELL_VAR = "yes"; then
...
I figure there must be some reason that I see this so often, but I can't figure out what it is.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
如果您不执行“x$SHELL_VAR”操作,那么如果 $SHELL_VAR 未定义,您会收到有关“=”不是单子运算符或类似内容的错误。
If you don't do the "x$SHELL_VAR" thing, then if $SHELL_VAR is undefined, you get an error about "=" not being a monadic operator or something like that.
如果您使用的 shell 执行简单替换,并且
SHELL_VAR
变量不存在(或为空),那么您需要注意边缘情况。 将发生以下翻译:第一个翻译将生成错误,因为
test
的第一个参数丢失了。 第二个则没有这个问题。您的情况翻译如下:
x
至少对于 POSIX 兼容的 shell 来说实际上是多余的,因为引号导致空参数和包含空格的参数都被解释为单个对象。If you're using a shell that does simple substitution and the
SHELL_VAR
variable does not exist (or is blank), then you need to watch out for the edge cases. The following translations will happen:The first of these will generate an error since the fist argument to
test
has gone missing. The second does not have that problem.Your case translates as follows:
The
x
, at least for POSIX-compliant shells, is actually redundant since the quotes ensue that both an empty argument and one containing spaces are interpreted as a single object.其他人尚未提及的另一个原因与选项处理有关。 如果你写:
并且$1的值为'-n',则测试命令的语法不明确; 目前尚不清楚您正在测试什么。 前面的“x”可以防止前导破折号造成麻烦。
您必须查看真正古老的 shell 才能找到测试命令不支持
-n
或-z
的 shell; 版本 7 (1978)test
命令包含了它们。 这并不是完全无关紧要的——一些版本 6 UNIX 的东西逃逸到 BSD 中,但现在,你很难找到当前使用的古老的东西。正如许多其他人指出的那样,在值周围不使用双引号是危险的。 事实上,如果文件名有可能包含空格(MacOS X 和 Windows 在某种程度上都鼓励这样做,并且 Unix 一直支持它,尽管像
xargs
这样的工具使它变得更难),那么你应该每次使用文件名时也将它们用双引号引起来。 除非您负责该值(例如,在选项处理期间,在启动时将变量设置为“no”,在命令行中包含标志时将变量设置为“yes”),否则使用不带引号的变量形式是不安全的直到你证明它们是安全的——而且你也可以为了多种目的一直这样做。 或者记录下,如果用户尝试处理名称中包含空格的文件,您的脚本将严重失败。 (还有其他字符也需要担心——例如,反引号也可能相当令人讨厌。)The other reason that no-one else has yet mentioned is in relation to option processing. If you write:
and $1 has the value '-n', the syntax of the test command is ambiguous; it is not clear what you were testing. The 'x' at the front prevents a leading dash from causing trouble.
You have to be looking at really ancient shells to find one where the test command does not have support for
-n
or-z
; the Version 7 (1978)test
command included them. It isn't quite irrelevant - some Version 6 UNIX stuff escaped into BSD, but these days, you'd be extremely hard pressed to find anything that ancient in current use.Not using double quotes around values is dangerous, as a number of other people pointed out. Indeed, if there's a chance that file names might contain spaces (MacOS X and Windows both encourage that to some extent, and Unix has always supported it, though tools like
xargs
make it harder), then you should enclose file names in double quotes every time you use them too. Unless you are in charge of the value (e.g. during option handling, and you set the variable to 'no' at startup and 'yes' when a flag is included in the command line) then it is not safe to use unquoted forms of variables until you've proved them safe -- and you may as well do it all the time for many purposes. Or document that your scripts will fail horribly if users attempt to process files with blanks in the names. (And there are other characters to worry about too -- backticks could be rather nasty too, for instance.)据我所知,这种约定有两个原因:
http://tldp.org/ LDP/abs/html/comparison-ops.html
其次,在 Bash 以外的其他 shell 中,尤其是较旧的 shell,不存在用于测试空变量的“-z”之类的测试条件,因此,
如果您的目标是跨各种 UNIX 的可移植性,则虽然这在 BASH 中可以正常工作在您无法确定默认 shell 是否为 Bash 以及它是否支持 -z 测试条件的环境中,使用 if [ "x$SOME_VAR" = "x" ] 形式更安全,因为它始终具有预期的结果影响。 本质上,这是一种用于查找空变量的旧 shell 脚本技巧,尽管有更简洁的方法可用,但它至今仍用于向后兼容。
There's two reasons that I know of for this convention:
http://tldp.org/LDP/abs/html/comparison-ops.html
Second, in other shells than Bash, especially older ones, the test conditions like '-z' to test for an empty variable did not exist, so while this:
will work fine in BASH, if you're aiming for portability across various UNIX environments where you can't be sure that the default shell will be Bash and whether it supports the -z test condition, it's safer to use the form if [ "x$SOME_VAR" = "x" ] since that will always have the intended effect. Essentially this is an old shell scripting trick for finding an empty variable, and it's still used today for backwards compatibility despite there being cleaner methods available.
我建议改为:
因为它消除了丑陋的
x
,并且仍然解决了 https:// /stackoverflow.com/a/174288/895245$SHELL_VAR
可以以-
开头并被读取为选项。I recommend instead:
since it does away with the ugly
x
, and still solves the problem mentioned by https://stackoverflow.com/a/174288/895245 that$SHELL_VAR
may start with-
and be read as an option.我相信这是由于
以及
但是
,这通常应该有效,
但是当它在其他地方的输出中抱怨时,很难说出它在抱怨什么,我猜,所以
也同样有效,但更容易调试。
I believe its due to
as well as
and
however, this should usually work
but when it complains in output somewhere else, its hard to tell what its complaining about I guess, so
works just as well, but would be easier to debug.
当 SHELL_VAR 可能未定义时,我曾经在 DOS 中这样做。
I used to do that in DOS when the SHELL_VAR might be undefined.