2013-12-16 66 views
3

參數是數組時,如何擴展參數?Bash中數組參數的間接參數擴展

如果參數是一個簡單的變量,我們可以使用感嘆號做一個間接尋址。

single_fruit() 
{ 
    if [ "$#" != 1 ]; then exit 1; fi 
    echo ${!1} 
} 

MYVAR=Persimmon 
single_fruit MYVAR 

我想對數組參數做同樣的事情。而不是遍歷直接數組的元素:

FRUIT=(Papaya Pineapple) 
for f in ${FRUIT[@]} 
do 
    echo ${f} 
done 

我想在函數中遍歷:

multi_fruit() 
{ 
    if [ "$#" != 1 ]; then exit 1; fi 
    PARAMETER=${1} 
    for i in ${!PARAMETER[@]} 
    do 
     echo ${i} 
    done 
} 

MOREFRUITS=(Mango Melon) 
multi_fruit MOREFRUITS 

你能做出對數組元素的這個最後的功能迭代?

+0

三個有用的和獨特的解決方案如下。我接受了需要最簡單的函數調用,並且推薦其他兩個的函數。 – Calaf

回答

2

你可以做到這一點,但在一個意想不到的方式:佔位符VAR需要包括數組索引:

multi_fruit() { 
    (($# != 1)) && return 1 
    tmp="${1}[@]" 
    for i in "${!tmp}"; do 
     echo "$i" 
    done 
} 

另外,僅使用大寫字母變量是個不錯的主意名。有一天,你會不小心覆蓋PATH,並想知道爲什麼你的腳本被破壞了。將大寫變量留給系統。

另請注意,將大括號放在變量周圍並不等同於雙引號。例如,考慮:

var="one two three" 
printf "%s\n" ${var} 
printf "%s\n" "$var" 
+0

編寫「$ {1} [@]」意味着我們只需附加文字[@]。隨後,擴展發生在數組名稱上,而文字[@]繼續進行。這是怎麼回事? – Calaf

+0

是的。不幸的是,bash開發者重載了'$ {!...' - 當應用於一個數組時,它給了你數組索引*:'declare -A x =([foo] = bar [baz] = qux); echo $ {!x [@]}'outputs'foo baz'(以某種順序) - 用一個「標量」變量,它執行間接性:因此''{!tmp}' –

2

在BASH中傳遞數組並不是直截了當的。事實上,數組甚至不會被導出到子shell。要將數組變量傳遞給函數,需要使用「ARRAY [@]」語法,然後使用變量間接運算符重構函數內部的數組。

考慮這個腳本:

multi_fruit() { 
    if [ "$#" != 1 ]; then exit 1; fi 
    # array reconstructions 
    arr=("${!1}") 
    for i in ${arr[@]} 
    do 
     echo ${i} 
    done 
} 

MOREFRUITS=(Mango Melon) 
multi_fruit "MOREFRUITS[@]" 

OUTPUT:

Mango 
Melon 
2

這工作:

multi_fruit() 
{ 
    if [ $# -lt 1 ]; then exit 1; fi 
    for i in "[email protected]" 
    do 
     echo ${i} 
    done 
} 

MOREFRUITS=(Mango Melon) 
multi_fruit "${MOREFRUITS[@]}" 
+0

有趣..我仍然試圖解析bash手冊頁中關於$ @特殊參數的說法。 – Calaf

+0

未加引號,'$ @'與'$ *'完全相同。它幾乎總是引用你使用'$ @'的特殊引用行爲,所以你應該總是使用引號:'「$ @」'。當不引用它時,使用'$ *'來提供一個線索,讓你有意將它放在不加引號的位置。 – chepner