5.1 引用变量

引用变量时,通常建议将变量包含在双引号中。因为这样可以防止除 $,` (反引号)和\(转义符)之外的其他特殊字符被重新解释。[^1]在双引号中仍然可以使用$引用变量("$variable"),也就是将变量名替换为变量值(详情查看样例 4-1)。

使用双引号可以防止字符串被分割。[^2]即使参数中拥有很多空白分隔符,被包在双引号中后依旧是算作单一字符。

1. List="one two three"

3. for a in $List     # 空白符将变量分成几个部分。
4. do
5. echo "$a"
6. done
7. # one
8. # two
9. # three

11. echo "---"

13. for a in "$List"   # 在单一变量中保留所有空格。
14. do #     ^     ^
15. echo "$a"
16. done
17. # one two three

下面是一个更加复杂的例子:

1. variable1="a variable containing five words"
2. COMMAND This is $variable1    # 带上7个参数执行COMMAND命令:
3. # "This" "is" "a" "variable" "containing" "five" "words"

5. COMMAND "This is $variable1"  # 带上1个参数执行COMMAND命令:
6. # "This is a variable containing five words"

9. variable2=""    # 空值。

11. COMMAND  $variable2 $variable2 $variable2
12. # 不带参数执行COMMAND命令。
13. COMMAND "$variable2" "$variable2" "$variable2"
14. # 带上3个参数执行COMMAND命令。
15. COMMAND "$variable2 $variable2 $variable2"
16. # 带上1个参数执行COMMAND命令(2空格)。

18. # 感谢 Stéphane Chazelas。

info 当字符分割或者保留空白符出现问题时,才需要在echo语句中用双引号包住参数。

样例 5-1. 输出一些奇怪的变量

1. #!/bin/bash
2. # weirdvars.sh: 输出一些奇怪的变量

4. echo

6. var="'(]\\{}\$\""
7. echo $var        # '(]\{}$"
8. echo "$var"      # '(]\{}$"     没有任何区别。

10. echo

12. IFS='\'
13. echo $var        # '(] {}$"     \ 被转换成了空格,为什么?
14. echo "$var"      # '(]\{}$"

16. # 上面的例子由 Stephane Chazelas 提供。

18. echo

20. var2="\\\\\""
21. echo $var2       #   "
22. echo "$var2"     # \\"
23. echo
24. # 但是...var2="\\\\"" 不是合法的语句,为什么?
25. var3='\\\\'
26. echo "$var3"     # \\\\
27. # 强引用是可以的。

30. # ************************************************************ #
31. # 就像第一个例子展示的那样,嵌套引用是允许的。

33. echo "$(echo '"')"           # "
34. #    ^           ^

37. # 在有些时候这种方法非常有用。

39. var1="Two bits"
40. echo "\$var1 = "$var1""      # $var1 = Two bits
41. #    ^                ^

43. # 或者,可以像 Chris Hiestand 指出的那样:

45. if [[ "$(du "$My_File1")" -gt "$(du "$My_File2")" ]]
46. #     ^     ^         ^ ^     ^     ^         ^ ^
47. then
48. ...
49. fi
50. # ************************************************************ #

单引号(’ ‘)与双引号类似,但是在单引号中不能引用变量,因为 $ 不再具有特殊含义。在单引号中,除'之外的所有特殊字符都将会被直接按照字面意思解释。可以认为单引号(“全引用”)是双引号(“部分引用”)的一种更严格的形式。

extra 因为在单引号中转义符(\)都已经按照字面意思解释了,因此尝试在单引号中包含单引号将不会产生你所预期的结果。

``` 1. echo "Why can't I write 's between single quotes"

  1. echo

  2. 可以采取迂回的方式。

  3. echo 'Why can'\''t I write '"'"'s between single quotes'
  4. |-------| |----------| |-----------------------|

  5. 由三个单引号引用的字符串,再加上转义以及双引号包住的单引号组成。

  6. 感谢 Stéphane Chazelas 提供的例子。

    ```

[^1]: 在命令行里,如果双引号包含了 “!” 将会产生错误。这是因为shell将其解释为查看历史命令。而在脚本中,因为历史机制已经被关闭,所以不会产生这个问题。 我们更加需要注意的是在双引号中 \ 的反常行为,尤其是在使用 echo -e 命令时。

1. bash$ echo hello\!
   hello!
   bash$ echo “hello\!”
   hello\!


   bash$ echo \
   >
   bash$ echo “\“
   >
   bash$ echo \a
   a
   bash$ echo “\a”
   \a


   bash$ echo x\ty
   xty
   bash$ echo “x\ty”
   x\ty

   bash$ echo -e x\ty
   xty
   bash$ echo -e “x\ty”
   x       y

在 echo 后的双引号中一般会转义 \。并且 echo -e 会将 "\t" 解释成制表符。 (感谢 Wayne Pollock 提出这些;感谢Geoff Lee 与 Daniel Barclay 对此做出的解释。) [^2]: 字符分割(word splitting)在本文中的意思是指将一个字符串分割成独立的、离散的变量。