在 shell script 中,我們可以像其他程式語言一樣使用 array,也可以使用 for loop 來走訪 array 的每個元素。
shell 中 array 的宣告與存取元素並沒有什麼特別之處,
值得注意的是在 shell 中存取變數時要加上${}
,
例如:
animals=(cat dog bird tiger lion)
echo ${animals[2]} # bird
而當我們直接存取宣告的變數時,會是存取到 array 的第一個元素:
echo $animals # cat
echo ${animals[0]} # cat
若想要存取 array 中的所有內容的話,可以使用@
或是*
,
但一般來說建議寫@
,理由後面會說明:
echo ${animals[@]} # cat dog bird tiger lion
echo ${animals[*]} # cat dog bird tiger lion
如果有寫過 python 應該可以明白, 在 python 中對 list 選擇範圍是很容易的事, 其實在 shell 中也是能用類似的語法簡單做到的:
echo ${animals[@]:1} # dog bird tiger lion
echo ${animals[@]:1:3} # cat dog bird tiger
echo ${animals[1]:1:3} # og
這種存取方法對普通的字串也是有用的
計算 array 的數量非常簡單,在變數名前面加上#
即可,這個方法在字串上也是可以用的:
echo ${#array[@]} # 5
echo ${#array[0]} # 3
結合剛剛提過的存取元素的語法就可以簡單在 for loop 中使用:
for animal in ${animals[@]}; do
echo $animal
done
# result
cat
dog
bird
tiger
lion
但是這麼寫會有一個重大缺陷,當 array 元素出現空白等元素時, 會造成結果不如預期,例如我們稍微換一下 array 中的元素:
animals=("cat" "dog" "bird tiger")
for animal in ${animals[@]}; do
echo "animal: $animal"
done
#result
animal: cat
animal: dog
animal: bird
animal: tiger
本來預期執行三次的迴圈,因為空白的出現導致變成了四次, 我們可以透過些微的修改迴圈的寫法來避免這樣的情形:
animals=("cat" "dog" "bird tiger")
for animal in "${animals[@]}"; do
echo "animal: $animal"
done
#result
animal: cat
animal: dog
animal: bird tiger
在變數的兩側加上引號"
可以避免這樣的問題,結果就正確了
[@]
與[*]
的差異還記得前面說過的列出所有元素時可以使用[@]
或是[*]
嗎?
事實上這兩種用法在某些情形下會有不同的行為,
比方說剛剛的例子我們換成使用星號*
animals=("cat" "dog" "bird tiger")
for animal in "${animals[*]}"; do
echo "animal: $animal"
done
#result
animal: cat dog bird tiger
這是什麼東西?怎麼只執行了一次?
但是若是去掉引號"
,這兩個的行為又完全一樣了。
看來@
與*
有展開方式的差異,在大部分的時候使用@
才會是符合預期的結果。
詳情可以參考這裡。