在shell脚本“ if”语句中引用变量


9

例如

if [ "$FOO" = "true" ]; then

if [ $FOO = "true" ]; then

有什么不同?似乎这两个语句也都起作用。


在Bash中,请使用双方括号,并且您不需要引号,并且可以得到其他好处
暂停,直到另行通知。

@DennisWilliamson不太完全,您确实需要在(in)等式和模式匹配运算符的右侧加引号。
吉尔(Gilles)'所以


@吉尔斯:有时候不行。对于包含空格的文字字符串,或者包含您想按字面意义使用的包含glob字符的文字字符串或变量,必须在右侧加上引号:a='foo bar'; [[ $a == "foo bar" ]]。但是,不包含全局字符的变量不必是:[[ $a == $a ]]。在双方括号内不执行单词扩展。而对于正则表达式匹配,在右侧的图案不得引用或将被当作文字字符串:[[ $a =~ .*oo.*r ]](模式应该是在未引用变量,但是,而不是...
。暂停,直至另行通知

像这里一样被并入)。对于glob样式的模式匹配,无论字面值还是在变量中,都不能用引号引起来[[ $a == foo* ]]。除了我的文字字符串示例外,您能否提供其他报价要求示例?
暂停,直到另行通知。

Answers:


6

如果的值$FOO是一个不包含通配符的单词\[*?,则两者相同。

如果$FOO未分配,为空或一个以上的单词(即包含空格或$IFS),则未引用的版本是语法错误。如果恰好是正确的单词序列(例如0 -eq 0 -o false),则结果可能是任意的。因此,优良作法是始终在Shell脚本中引用变量。

顺便说一句,"true"不需要引用。


3

为了说明它可能引起什么问题,这里有一些示例。

假设我们有两个变量,如下所示:

FOO="some value"
BAR="some value"

现在,我们有两个变量拥有完全相同的字符串/值。如果我们做了一些if语句来测试结果,那么在您的情况下:

if [ $FOO = "$BAR" ]; then echo "match"; else echo "no match"; fi

此时您将获得bash: [: too many arguments。无引号的$ FOO现在具有三个值,即'[ , some , value'[test关键字不知道要执行什么,因为它期望第一个或第二个参数为运算符。

当我们引用“ $ FOO”时,我们明确告诉if要查看没有分词发生的正确值。

另一个例子:

my_file="A random file.txt"
  • 这样做rm $my_file意味着删除“ A”“随机”“ file.txt”,这使其成为三个文件。
  • 这样做rm "$my_file"会删除制作一个文件的“ A random file.txt”。

希望我不会让您对这些示例感到困惑。


0

在这种特定情况下,没有区别。

但是,如果$FOO包含空格或某些特殊字符,则会出现问题。

在这种"$FOO"情况下,它将总共使用该变量,以使匹配与空间问题隔离开。

但是,如果使用$FOO并且有特殊情况,它将影响if语句。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.