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

Mee*_*kat 23 shell bash quoting test variable

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

value1=5
value2=3
Run Code Online (Sandbox Code Playgroud)

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

if [[ "$value1" -eq "$value2" ]]
Run Code Online (Sandbox Code Playgroud)

为什么不使用以下内容?

if [[ $value1 -eq $value2 ]]
Run Code Online (Sandbox Code Playgroud)

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

ter*_*don 35

您实际上并不需要这里的引号。这是使用不带引号的变量是安全的极少数情况之一。您可以通过以下方式确认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!
Run Code Online (Sandbox Code Playgroud)

正如您在上面看到的,测试的引用和未引用版本被 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!
Run Code Online (Sandbox Code Playgroud)

[ ]构造不同,该构造[[ ]]确实需要引用。


一些有用的链接可以了解有关何时以及为何需要引用的更多信息:

  • 注意 `-eq` 是 _arithmetic_ 比较,所以你甚至可以把 `$` 去掉(在 `[[ .. ]]` 中),而写成 `[[ a -eq b ]]`。对于字符串比较,当然需要`$`,所以`[[ $a = $b ]]` (5认同)
  • @ilkkachu,这让我感到惊讶。我认为“裸”变量只会在数组下标或 `((...))` 或 `$((...)` 中被考虑。它似乎有效,但是(脾气暴躁的老男人,启用)我不喜欢。 (3认同)
  • @user000001 好点。当然,虽然你很可能_想要_那些扩展。例如,我希望这是一个匹配项:`var1="afoob"; var2="a*b"; [[ $var1 = $var2 ]] && 回声匹配`。如果您想使用 glob 字符而不将它们用作 globbing 上下文中的 glob(例如`[[]]`),那么您需要引用,是的。 (2认同)
  • @glennjackman,好吧,很抱歉告诉您这一点,但是,是的,`-eq` 的操作数和 `[[ ]]` 中的朋友也是算术上下文。:)(相关:[bash \[\[ \]\] 命令中的自动变量扩展](https://unix.stackexchange.com/q/485766/170373)) (2认同)

jam*_*lin 16

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

  • 好的做法/习惯:在这种情况下,它们不是必需的,但通常双引号为了避免意外的分词。
  • 因为value1value2是可变的,您可能不知道它们包含什么。否则你可能会问,“为什么要费心去检查变量而不是检查if [[ 5 -eq 3 ]]?或者更进一步,if当你已经知道 5 不等于 3 时,为什么还要费心呢?防守通常更好。(这是真的在[[不会发生分词,但不会发生分词的情况很少见。同样,请参见第一点。)


gle*_*man 7

分词。

这个例子不太可能,但可能,所以如果你想防御性地编码,用引号覆盖你的踪迹:

$ set -x
$ value1=5
+ value1=5
$ value2=3
+ value2=3
$ [ $value1 -eq $value2 ]
+ '[' 5 -eq 3 ']'
Run Code Online (Sandbox Code Playgroud)

好的,到目前为止一切顺利。让我们把扳手扔进齿轮:

$ IFS=456
+ IFS=456
$ [ $value1 -eq $value2 ]
+ '[' '' -eq 3 ']'
bash: [: : integer expression expected
Run Code Online (Sandbox Code Playgroud)

哎呀。

$ [ "$value1" -eq "$value2" ]
+ '[' 5 -eq 3 ']'
Run Code Online (Sandbox Code Playgroud)

啊。

  • 是的,这与 bash 的 `[[]]` 构造并没有真正的相关性。 (5认同)
  • 但是 OP 使用双括号,因此不会发生分词。 (2认同)
  • 这个答案与问题没有“直接”相关。我很惊讶它被接受了。设置为社区 wiki。 (2认同)

归档时间:

查看次数:

2847 次

最近记录:

6 年,4 月 前