
在 shell 腳本中,如果我定義一個變量,例如,將其引用為和FOO=25
之間有區別嗎?$FOO$
${FOO}$
答案1
在大多數情況下,兩者$var
和${var}
是相同的。 (請注意,$
最後不能使用 a !)
需要花括號的範例是需要將變數放入連續字串中。
例子:
var=hel
echo ${var}lo
將輸出hello
.
答案2
為了回答你的主要問題,${foo}
稱為“參數擴展”。準確的說,是$
自身開始參數擴展,{ }
實際上是可選的,根據POSIX 規範,但可用於指示變數名稱的結尾:
$ foo="bar"
$ echo $fooBaz ## fails, no variable named $fooBaz exists
$ echo ${foo}Baz ## works, $foo is expanded and the string Baz is appended
barBaz
基本上,$foo
並且${foo}
是相同的。除了上述情況或當你在做的時候字串操作,它們是完全等價的。
但是,您不應該真正使用它們中的任何一個。經驗法則是,除了極少數例外,您應該總是使用"$foo"
or"${foo}"
且從不使用$foo
or ${foo}
。您應該始終引用變數以避免呼叫 split+glob 運算子(稍後會詳細介紹)。你當然不要$foo$
。最後的結果$
是無關緊要的:
$ foo="bar"
$ echo "$foo$"
bar$
因此,雖然不帶引號的變數有時是可以的:
$ echo $foo
bar
它們通常不是並且確實應該避免:
$ if [ -n $foo ]; then echo empty; else echo "not empty"; fi ## fails
empty
$ if [ -n "$foo" ]; then echo empty; else echo "not empty"; fi ## works
not empty
請注意,括號在這裡也沒有幫助:
$ if [ -n ${foo} ]; then echo empty; else echo "not empty"; fi ## fails
empty
$ if [ -n "${foo}" ]; then echo empty; else echo "not empty"; fi ## works
not empty
當您使用$foo
或${foo}
,外殼將分裂儲存在變數中空白處的值(可以透過設定來更改IFS
其他值來變更)儲存到清單中,然後清單中的每個元素都被視為一個全域模式並擴展到任何符合的檔案或目錄。這被稱為分割+全域操作員。為了說明這一點,請考慮一個包含兩個檔案的目錄:
$ ls -l
-rw-r--r-- 1 terdon terdon 0 Oct 9 18:16 file1
-rw-r--r-- 1 terdon terdon 0 Oct 9 18:16 file2
現在,讓我們將變數設定為foo *
:
$ foo="foo *"
如果我們嘗試檢查具有該名稱的檔案是否存在會發生什麼?
$ if [ -e $foo ]; then echo "file exists"; else echo "no such file"; fi
file exists
該變數被拆分為foo
and *
,因為 and*
是匹配任何字串的通配符,因此 shell 會告訴您存在一個名為foo *
exists 的檔案。但是,如果我們正確引用它,則不會發生這種情況:
$ if [ -e "$foo" ]; then echo "file exists"; else echo "no such file"; fi
no such file
這是一個簡單的例子來說明這一點。想像一下,如果我用「雖然」rm
來代替echo
。
所以,第一條規則:總是引用你的變數。您可以使用"$foo"
或"${foo}"
但以任何一種方式引用它。有關安全使用變數的更多詳細信息,請查看這些帖子: