假设 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
尽管双引号不是必需的,但使用它们的原因是:
- 良好的做法/习惯:在这情况下它们不是必需的,但通常是双引号是以避免意外的分词。
- 因为
value1
和value2
是可变的,你可能不知道它们包含什么。否则你可能会问,“为什么要费心去处理变量而不是检查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 脚本具有更好的可读性在代码突出显示编辑器中。