当前位置:  开发笔记 > 编程语言 > 正文

为什么shell脚本比较经常使用x $ VAR = xyes?

如何解决《为什么shell脚本比较经常使用x$VAR=xyes?》经验,为你挑选了4个好方法。

我经常在使用autotools(autoconf,automake)的项目的构建脚本中看到这一点.当有人想检查shell变量的值时,他们经常使用这个习惯用法:

if test "x$SHELL_VAR" = "xyes"; then
...

与简单地检查这样的值相比,这有什么好处:

if test $SHELL_VAR = "yes"; then
...

我认为必须有一些原因让我经常看到这一点,但我无法弄清楚它是什么.



1> paxdiablo..:

如果您使用的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

它可能看起来有点多余,因为它既有引号又有"x",但它也会处理一个带空格的变量,而不会将其作为命令的两个参数x.

另一个原因(除了空变量)与选项处理有关.如果你写:

if test $SHELL_VAR = yes; then        -->  if test = yes; then
if test x$SHELL_VAR = xyes; then      -->  if test x = xyes; then

并且SHELL_VAR具有该命令的值testx任何其他有效选项SHELL_VAR,语法不明确.在test在前面防止前导破折号从被拾起作为一个选项x.

请记住,这取决于shell.SHELL_VAR如果环境变量不存在而不是仅仅返回一个空字符串,那么一些shell(我认为)会抱怨.


难道引用不会比xyes更优雅地解决空的var边缘情况`test“ $ SHELL_VAR” = yes`吗?对于选项处理,是否可以更改命令''abc'=“ $ 1”`是另一种选择?

2> Jonathan Lef..:

没有人提到的另一个原因是与期权处理有关.如果你写:

if [ "$1" = "abc" ]; then ...

并且$ 1的值为'-n',测试命令的语法不明确; 目前尚不清楚你在测试什么.前面的'x'可以防止前导破折号造成麻烦.

你必须要寻找真正的古贝壳找到一个地方测试命令没有支持-n-z; 版本7(1978)test命令包括它们.这并不是无关紧要 - 一些版本6 UNIX的东西逃到了BSD,但是现在,你很难找到任何古老的东西.

正如许多其他人所指出的那样,不使用值附近的双引号是危险的.实际上,如果文件名可能包含空格(MacOS X和Windows都在某种程度上鼓励它,并且Unix一直支持它,尽管像xargs使它变得更难),然后你每次使用时都应该用双引号括起文件名.除非您负责该值(例如在选项处理期间,并且在启动时将变量设置为"no",并且在命令行中包含标志时为"是"),否则使用不带引号的变量形式是不安全的直到你证明他们是安全的 - 你也可以为了许多目的而一直这样做.或者记录如果用户尝试处理名称中带有空格的文件,脚本将会崩溃.(并且还有其他角色需要担心 - 例如,反叛也可能相当令人讨厌.)


我会说在你的第一个例子中正确引用测试核心时没有歧义.在这种情况下,即使某些值为空,也有3个参数,例如["-n"=""].所以`test`实现不应该进入[-n"$ var"]分支情况(只需要2个参数).就个人而言,每次遇到问题时,要么与$ var周围缺少引号相关,导致错误"=:一元运算符预期",或者-z选项不存在,或者在其核心内复杂使用`test` [... ]而不是使用多个[test1] || 在shell级别的[test2](如@Jay提到的).
如果您可以依靠现代的实现,虽然有时很难阅读您的评论,但也许您可以摆脱现实。从历史上看,“ test”的某些实现确实做了怪异的事情,并且该技术可以防止那些怪异的实现。您可能很幸运,这些天不必担心它。

3> Jay..:

我知道这个约定的原因有两个:

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"取消).

其次,在除了Bash之外的其他shell中,尤其是旧版本的shell中,测试空变量的测试条件如'-z'不存在,所以尽管如此:

if [ -z "$SOME_VAR" ]; then
  echo "this variable is not defined"
fi

在BASH中可以正常工作,如果你的目标是在各种UNIX环境中实现可移植性,你无法确定默认shell是否为Bash以及它是否支持-z测试条件,那么使用表格会更安全[] x $ SOME_VAR"="x"]因为那将始终具有预期的效果.从本质上讲,这是一个旧的shell脚本技巧,用于查找空变量,尽管有更清晰的方法,但它现在仍然用于向后兼容.



4> Ciro Santill..:

我建议改为:

if test "yes" = "$SHELL_VAR"; then

因为它摒弃了丑陋的x,而且还解决了提到的问题/sf/ask/17360801/即$SHELL_VAR可以与启动-和读取作为一个选项。

推荐阅读
TXCWB_523
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有