# 5.1 引用變量
引用變量時,通常建議將變量包含在雙引號中。因為這樣可以防止除 `$`,`` ` ``(反引號)和`\`(轉義符)之外的其他特殊字符被重新解釋。[^1]在雙引號中仍然可以使用`$`引用變量(`"$variable"`),也就是將變量名替換為變量值(詳情查看樣例 4-1)。
使用雙引號可以防止字符串被分割。[^2]即使參數中擁有很多空白分隔符,被包在雙引號中后依舊是算作單一字符。
```bash
List="one two three"
for a in $List # 空白符將變量分成幾個部分。
do
echo "$a"
done
# one
# two
# three
echo "---"
for a in "$List" # 在單一變量中保留所有空格。
do # ^ ^
echo "$a"
done
# one two three
```
下面是一個更加復雜的例子:
```bash
variable1="a variable containing five words"
COMMAND This is $variable1 # 帶上7個參數執行COMMAND命令:
# "This" "is" "a" "variable" "containing" "five" "words"
COMMAND "This is $variable1" # 帶上1個參數執行COMMAND命令:
# "This is a variable containing five words"
variable2="" # 空值。
COMMAND $variable2 $variable2 $variable2
# 不帶參數執行COMMAND命令。
COMMAND "$variable2" "$variable2" "$variable2"
# 帶上3個參數執行COMMAND命令。
COMMAND "$variable2 $variable2 $variable2"
# 帶上1個參數執行COMMAND命令(2空格)。
# 感謝 Stéphane Chazelas。
```
>  當字符分割或者保留空白符出現問題時,才需要在`echo`語句中用雙引號包住參數。
樣例 5-1. 輸出一些奇怪的變量
```bash
#!/bin/bash
# weirdvars.sh: 輸出一些奇怪的變量
echo
var="'(]\\{}\$\""
echo $var # '(]\{}$"
echo "$var" # '(]\{}$" 沒有任何區別。
echo
IFS='\'
echo $var # '(] {}$" \ 被轉換成了空格,為什么?
echo "$var" # '(]\{}$"
# 上面的例子由 Stephane Chazelas 提供。
echo
var2="\\\\\""
echo $var2 # "
echo "$var2" # \\"
echo
# 但是...var2="\\\\"" 不是合法的語句,為什么?
var3='\\\\'
echo "$var3" # \\\\
# 強引用是可以的。
# ************************************************************ #
# 就像第一個例子展示的那樣,嵌套引用是允許的。
echo "$(echo '"')" # "
# ^ ^
# 在有些時候這種方法非常有用。
var1="Two bits"
echo "\$var1 = "$var1"" # $var1 = Two bits
# ^ ^
# 或者,可以像 Chris Hiestand 指出的那樣:
if [[ "$(du "$My_File1")" -gt "$(du "$My_File2")" ]]
# ^ ^ ^ ^ ^ ^ ^ ^
then
...
fi
# ************************************************************ #
```
單引號(' ')與雙引號類似,但是在單引號中不能引用變量,因為 `$` 不再具有特殊含義。在單引號中,除`'`之外的所有特殊字符都將會被直接按照字面意思解釋。可以認為單引號(“全引用”)是雙引號(“部分引用”)的一種更嚴格的形式。
>  因為在單引號中轉義符(\)都已經按照字面意思解釋了,因此嘗試在單引號中包含單引號將不會產生你所預期的結果。
>
```bash
echo "Why can't I write 's between single quotes"
>
echo
>
# 可以采取迂回的方式。
echo 'Why can'\''t I write '"'"'s between single quotes'
# |-------| |----------| |-----------------------|
# 由三個單引號引用的字符串,再加上轉義以及雙引號包住的單引號組成。
>
# 感謝 Stéphane Chazelas 提供的例子。
```
[^1]: 在命令行里,如果雙引號包含了 "!" 將會產生錯誤。這是因為shell將其解釋為查看歷史命令。而在腳本中,因為歷史機制已經被關閉,所以不會產生這個問題。<br>我們更加需要注意的是在雙引號中 `\` 的反常行為,尤其是在使用 `echo -e` 命令時。<br><pre>bash$ echo hello\\!<br>hello!<br>bash$ echo "hello\\!"<br>hello\\!<br><br><br>bash$ echo \\<br>><br>bash$ echo "\\"<br>><br>bash$ echo \a<br>a<br>bash$ echo "\a"<br>\a<br><br><br>bash$ echo x\ty<br>xty<br>bash$ echo "x\ty"<br>x\ty<br><br>bash$ echo -e x\ty<br>xty<br>bash$ echo -e "x\ty"<br>x y</pre>在 `echo` 后的雙引號中一般會轉義 `\`。并且 `echo -e` 會將 `"\t"` 解釋成制表符。<br>(感謝 Wayne Pollock 提出這些;感謝Geoff Lee 與 Daniel Barclay 對此做出的解釋。)
[^2]: 字符分割(word splitting)在本文中的意思是指將一個字符串分割成獨立的、離散的變量。
- 第一部分 初見shell
- 1. 為什么使用shell編程
- 2. 和Sha-Bang(#!)一起出發
- 2.1 調用一個腳本
- 2.2 牛刀小試
- 第二部分 shell基礎
- 3. 特殊字符
- 4. 變量與參數
- 4.1 變量替換
- 4.2 變量賦值
- 4.3 Bash弱類型變量
- 4.4 特殊變量類型
- 5. 引用
- 5.1 引用變量
- 5.2 轉義
- 6. 退出與退出狀態
- 7. 測試
- 7.1 測試結構
- 7.2 文件測試操作
- 7.3 其他比較操作
- 7.4 嵌套 if/then 條件測試
- 7.5 牛刀小試
- 8. 運算符相關話題
- 8.1 運算符
- 8.2 數字常量
- 8.3 雙圓括號結構
- 8.4 運算符優先級
- 第三部分 shell進階
- 10. 變量處理
- 10.1 字符串處理
- 10.1.1 使用 awk 處理字符串
- 10.1.2 參考資料
- 10.2 參數替換
- 11. 循環與分支
- 11.1 循環
- 11.2 嵌套循環
- 11.3 循環控制
- 11.4 測試與分支
- 12. 命令替換
- 13. 算術擴展
- 14. 休息時間
- 第五部分 進階話題
- 19. 嵌入文檔
- 20. I/O 重定向
- 20.1 使用 exec
- 20.2 重定向代碼塊
- 20.3 應用程序
- 22. 限制模式的Shell
- 23. 進程替換
- 26. 列表結構
- 25. 別名