shell 脚本,当您使用'-o'选项并且只有一个变量时会发生什么?



例如,当运行以下shell脚本时:

foo="example"

if [ -o $foo ]; then
foo="true"
echo $foo
fi

结果为false,不返回任何内容。

但是如果foo的值为null

foo=" "

if [ -o $foo ]; then
foo="true"
echo $foo
fi

返回真值。

操作foo = "example"如果[$foo -o $foo]在shell脚本中是可以理解的。(I understand that value is true.)

然而,如果foo = "abc"如果[-o $foo],我将其理解为null或true ($foo value)。

结果是错误的,与我的期望相反。

这是什么原因?

一些事实:

  • 在bash中,[ -o OPTION ]中的-o是测试shell选项option是否被启用的操作符。
  • [ STRING ]测试STRING是否为空。
  • 内部单括号([ ]),如果$foo没有被引用,它将进行分词

:

  • 对于foo=' '; [ -o $foo ],执行的测试是[ -o ]-o不是空字符串,所以它返回true
  • opt=posix; set -o $opt; [ -o $opt ]返回true,因为设置了选项posix
  • opt=posix; set +o $opt; [ -o $opt ]返回false,因为选项posix未设置。

在双括号测试语法中,不发生分词。所以在foo=' '; [[ -o $foo ]]中,空间是保留的。执行的测试是[[ -o <space> ]],它返回false,因为(一个文字空格)不是一个可启用的shell选项。

我建议使用双括号,除非你有很好的理由不这么做。单括号测试语法主要是为了兼容POSIX和遗留的bourne shell脚本。

如果您使用单括号,请引用所有变量,以防止分词和全局展开(这不会发生在双括号内)。

阅读bash源代码:

案例1:foo="example"; [ -o $foo ][ -o example ]

案例1 b:foo=""; [ -o "$foo" ][ -o □ ]

  • 使用□表示参数为空字符串
  • 解析为两个参数
  • 第一个参数(-o)匹配一元操作符"find_option_o_value">
  • 第二个参数不是有效的选项名
  • 结果:false(未找到)
    • 注意:当第二个参数是一个有效的选项名时,返回值将指示该选项是否被设置(true⇒enabled, false⇒disabled)

案例2:foo=" "; [ -o $foo ][ -o ]

案例2 b:foo=" "; [ $foo -o $foo ][ -o ]

  • 解析为一个参数
  • 参数(-o)是非空
  • 结果:真正的

案例3:foo=""; [ "$foo" -o "$foo" ][ □ -o □ ]

  • 使用□表示参数为空字符串
  • 解析为三个参数
  • 第二个参数是ANDOR运算符
  • 第一个和第三个参数都不为非空
  • 结果:假

案例4:foo=""; [ "$foo" -o $foo ][ □ -o ]

  • 使用□表示参数为空字符串
  • 解析为两个参数
  • 第一个参数不是一元操作符
  • result: false(语法错误)

如果不引用变量,并且变量为空,或者只有空白(即$IFS中的空白),则命令根本看不到。所以test -o $foo和test -o

是一样的我不认为它返回true有什么特别好的理由,你所做的是病态的,没有任何意义。你需要做的是对变量加双引号,这样可以保证测试可以看到这里有一些东西,然后它会对它做一些合理的处理。作为一般规则,总是双引号的东西,你通过测试,以防万一它是空的。

最新更新