Bash 提供兩種參數型別:純量值和陣列。 純量值可以是字串或數字,代表單一的「東西」。
大多數情況下,純量值就足以存放你的資料。 但有時候,你需要儲存一連串的純量值。 這時你就會用到_陣列_。
陣列有兩種:
本文件開頭幾節會介紹以數字索引的陣列(以下簡稱「陣列」)。 關於關聯式陣列的細節會出現在最後面。
Bash 陣列_只能_儲存純量值。 沒有辦法建立二維陣列(陣列的陣列)。
你可以把一串用括號括起來的元素清單(可以是空的)指定給變數,藉此初始化陣列。
myarray=("one" "two" "three")
如同所有的變數賦值,等號兩邊不能有空格。
請注意,元素之間沒有逗號分隔;這是一份以空白分隔的字串清單。
事實上,括號內要放多少空白完全隨意。 也可以換行;想用幾行就用幾行,讓程式更好讀。
myarray=(
"first element"
"second element"
"this is the last element"
)
用這種方式把字串清單指定給陣列變數,會把第一個字串存在索引 0,下一個存在索引 1,再下一個存在索引 2,以此類推。
你也可以明確指定需要的索引,來初始化「稀疏陣列」。
raindrops=([3]="Pling" [5]="Plang" [7]="Plong")
再強調一次:陣列索引是從零開始的。 這段程式碼會輸出 "true":
myarray=("one" "two" "three")
[[ "${myarray[0]}" == "one" ]] && echo true || echo false
你可以使用declare指令(在函式內則是local)來指定某個變數會存放陣列。
declare -a myarray
更道地的做法是直接指定一串(可能是空的)括號清單來初始化變數。
如上面的注意事項所述,存取陣列元素的語法是${myarray[$index]}。
索引寫在方括號裡。
大括號是必要的。
對以數字索引的陣列來說,索引是一個算術運算式。 Bash 手冊指出:
在算術運算式中,也可以直接用名稱參照 shell 變數,而不使用參數展開語法。
這表示「簡單的」變數展開並不需要$。
你可以像這樣存取元素,讀起來比較容易:
i=5
echo "${myarray[i]}"
# ..............^
如果指定的索引不存在於陣列中,展開的結果會是空字串。
要指定某個特定的陣列項目,請使用這個語法:
myarray[10]="hello"
要_附加_到陣列,請使用+=這個串接賦值運算子,並加上括號:
myarray+=("new element 1" "new element 2")
你通常會需要疊代陣列的_值_。
使用for迴圈(你在迴圈概念中看過):
myarray=("one" "two" "three")
for value in "${myarray[@]}"; do
echo "$value"
done
請注意展開陣列的特殊語法:"${myarray[@]}"
這種參數展開形式會把陣列的值替換成各自獨立的詞。
這大致等同於:
for value in "${myarray[0]}" "${myarray[1]}" ... "${myarray[n]}"
"${myarray[@]}"這種形式也能用在稀疏陣列上,只會展開已定義的值。
這種特殊展開(索引是@符號)只有在雙引號內才具有特殊意義。
這裡還有幾個疊代陣列時會用到的特殊語法。 手冊在參數展開一節中有說明。
要找出陣列的_長度_,請使用${#myarray[@]},在名稱前面加上#。
陣列的「長度」指的是其中元素的數量。
要取出陣列的_索引_清單,請使用"${!myarray[@]}",在名稱前面加上!,並把展開式放在雙引號內。
對以數字索引的陣列來說,索引會依數字順序展開。
有時候你除了值之外,也需要索引。 有幾種做法。
當你知道索引是連續不中斷的,可以使用_算術_for迴圈。
for ((i = 0; i < ${#myarray[@]}; i++)); do
echo "$i -> ${myarray[i]}"
done
請注意${#myarray[@]}這個語法,#字元放在陣列名稱前面。
由於陣列使用從零開始的索引,陣列的最後一個索引會比陣列長度少一。
當陣列是稀疏的,可以使用這種形式:
for index in "${!raindrops[@]}"; do
echo "$index -> ${raindrops[index]}"
done
請注意${!myarray[@]}這個語法,!字元放在陣列名稱前面。
如果你想看看陣列的內容,請使用帶有-p選項的declare指令:
a=("the 'first' element"
second
third
'the "last" element')
declare -p a
這會以 shell 的標準引號格式輸出內容。
declare -a a=([0]="the 'first' element" [1]="second" [2]="third" [3]="the \"last\" element")
再次強調,關聯式陣列使用字串作為索引,而不是數字。 上面寫的一切都適用於關聯式陣列,只是有些小差異。 一般來說,我們會說「鍵」而不是「索引」:關聯式陣列把鍵對應到值。
和陣列不同,關聯式陣列必須先宣告。
請使用declare的-A選項(在函式內則是local):
declare -A mymap
myfunc() {
local -A my_local_map
# ...
}
鍵值對寫在括號清單裡:
mymap=([first]=foo [second]=bar [third]=baz)
declare -p mymap
輸出結果為:
declare -A mymap=([second]="bar" [first]="foo" [third]="baz")
請注意,關聯式陣列是無序的。
宣告和初始化可以寫在同一行。
declare -A mymap=([first]=foo [second]=bar [third]=baz)
在較新的 Bash 版本中,初始化可以使用(key value key value ...)這種清單。
declare -A mymap=(first foo second bar third baz)
存取元素使用和之前相同的語法:${mymap[$key]}。
關聯式陣列的鍵不會在算術情境中求值。 必須使用一般的參數展開語法。
賦值使用和之前相同的語法:
mymap[$key]="$value"
你可以用for value in "${mymap[@]}"迴圈來疊代。
不過,你通常也會想要連同值一起取得鍵。
請使用我們上面看過的"${!mymap[@]}"語法。
for key in "${!mymap[@]}"; do
echo "$key -> ${mymap[$key]}"
done
輸出結果為
second -> bar
first -> foo
third -> baz
再次強調,鍵沒有順序。