为什么在 [[ ]] 测试中使用双引号?

为什么在 [[ ]] 测试中使用双引号?

假设 bash 脚本中有 2 个整数:

value1=5
value2=3

那么为什么我们在测试时需要使用双引号呢?例如:

if [[ "$value1" -eq "$value2" ]]

为什么不直接使用以下内容呢?

if [[ $value1 -eq $value2 ]]

对我来说,双引号没有任何意义。

答案1

您实际上不需要这里的引号。这是可以安全使用不带引号的变量的极少数情况之一。您可以通过以下方式确认set -x

$ var1=""
$ var2="3"
$ set -x
$ if [[ $var1 -eq $var2 ]]; then echo "match!"; else echo "no match!"; fi
+ [[ '' -eq 3 ]]
+ echo 'no match!'
no match!
$ if [[ "$var1" -eq "$var2" ]]; then echo "match!"; else echo "no match!"; fi
+ [[ '' -eq 3 ]]
+ echo 'no match!'
no match!

正如您在上面看到的,带引号和不带引号的测试版本被 bash 解析为完全相同的内容。zsh我认为,对于支持该运算符的任何其他 shell 也应该如此[[ ]]

请注意,这是不是更便携的情况[ ]

$ if [ $var1 -eq $var2 ]; then echo "match!"; else echo "no match!"; fi
+ '[' -eq 3 ']'
sh: [: -eq: unary operator expected
+ echo 'no match!'
no match!

与之前的构造不同,该[ ]构造[[ ]]确实需要引用。


一些有用的链接可帮助您详细了解何时以及为何需要引用:

答案2

尽管双引号不是必需的,但使用它们的原因是:

  • 良好的做法/习惯:在情况下它们不是必需的,但通常是双引号以避免意外的分词。
  • 因为value1value2是可变的,你可能不知道它们包含什么。否则你可能会问,“为什么要费心去处理变量而不是检查if [[ 5 -eq 3 ]]?或者更进一步,if当你已经知道 5 不等于 3 时,为什么还要费心去处理 呢?通常最好采取防御性的态度。(确实如此)分词不会发生在 中[[,但是分词的情况会发生不是发生的情况很少见。再次参见第一点。)

答案3

分词。

这个例子是非常不可能的但有可能,因此,如果你想要防御性地编写代码,请使用引号掩盖你的踪迹:

$ set -x
$ value1=5
+ value1=5
$ value2=3
+ value2=3
$ [ $value1 -eq $value2 ]
+ '[' 5 -eq 3 ']'

好的,到目前为止一切都很好。让我们把扳手放到齿轮上:

$ IFS=456
+ IFS=456
$ [ $value1 -eq $value2 ]
+ '[' '' -eq 3 ']'
bash: [: : integer expression expected

哎呀。

$ [ "$value1" -eq "$value2" ]
+ '[' 5 -eq 3 ']'

啊。

答案4

你是绝对正确的!

双方括号内的引用根本没有意义,至少在这种情况下是这样。

但由于我每天都使用双引号——特别是对于单方括号表达式、向函数和脚本传递参数,以及有时变量赋值(这对于简单的声明完全没有用)——我猜有些人,至少我是,本能地在变量扩展周围写上双引号

双引号可以给你一种安全感。就像回到双引号所在的地方一样。 - D.库默尔

做事的好处因此并且可以理解地使用双引号——但只有在有意义的情况下——刚接触 bash 的同事才可以学习如何编写更稳定的脚本。它还强调了这样一个事实:使用 bash 进行数据处理的艺术更多的是关于通过字段分隔符分隔数据流(包括变量)并通过过滤器通过管道传输它们。一旦你将数据块从流中分离出来,用双引号将它们放在一起!

另一个好处是带有双引号字符串的 bash 脚本具有更好的可读性在代码突出显示编辑器中

相关内容