57

連想配列を引数として関数に渡すにはどうすればよいですか? これはBashで可能ですか?

以下のコードは期待どおりに動作しません。

function iterateArray
{
    local ADATA="${@}"            # associative array

for key in "${!ADATA[@]}"
do
    echo "key - ${key}"
    echo "value: ${ADATA[$key]}"

done

}

連想配列を通常の配列のような関数に渡すことは機能しません:

iterateArray "$A_DATA"

また

iterateArray "$A_DATA[@]"
4

9 に答える 9

51

私は先週まったく同じ問題を抱えていて、かなり長い間考えていました.

連想配列はシリアル化またはコピーできないようです。連想配列について詳しく説明しているBash FAQ の優れたエントリがあります。最後のセクションでは、私に役立つ次のアイデアが得られました。

function print_array {
    # eval string into a new associative array
    eval "declare -A func_assoc_array="${1#*=}
    # proof that array was successfully created
    declare -p func_assoc_array
}

# declare an associative array
declare -A assoc_array=(["key1"]="value1" ["key2"]="value2")
# show associative array definition
declare -p assoc_array

# pass associative array in string form to function
print_array "$(declare -p assoc_array)" 
于 2012-01-16T11:35:17.573 に答える
51

Bash 4.3 以降を使用している場合、最もクリーンな方法は、連想配列を名前で渡し、 を使用した名前参照を使用して関数内でアクセスすることlocal -nです。例えば:

function foo {
    local -n data_ref=$1
    echo ${data_ref[a]} ${data_ref[b]}
}

declare -A data
data[a]="Fred Flintstone"
data[b]="Barney Rubble"
foo data

_refサフィックスを使用する必要はありません。それは私がここで選んだものです。元の変数名とは異なる限り、任意の参照を呼び出すことができます (そうしないと、「循環名参照」エラーが発生します)。

于 2019-03-14T19:19:24.630 に答える
15

Florian Feldhaus のソリューションに基づく:

# Bash 4+ only
function printAssocArray # ( assocArrayName ) 
{
    var=$(declare -p "$1")
    eval "declare -A _arr="${var#*=}
    for k in "${!_arr[@]}"; do
        echo "$k: ${_arr[$k]}"
    done

}

declare -A conf
conf[pou]=789
conf[mail]="ab\npo"
conf[doo]=456

printAssocArray "conf" 

出力は次のようになります。

doo: 456
pou: 789
mail: ab\npo
于 2015-09-12T07:59:50.353 に答える
9

更新、質問に完全に答えるために、ここに私のライブラリからの小さなセクションがあります:

参照による連想配列の反復

shopt -s expand_aliases
alias array.getbyref='e="$( declare -p ${1} )"; eval "declare -A E=${e#*=}"'
alias array.foreach='array.keys ${1}; for key in "${KEYS[@]}"'

function array.print {
    array.getbyref
    array.foreach
    do
        echo "$key: ${E[$key]}"
    done
}

function array.keys {
    array.getbyref
    KEYS=(${!E[@]})
}   

# Example usage:
declare -A A=([one]=1 [two]=2 [three]=3)
array.print A

これは私の以前の作品の開発であり、以下に残します。

@ffeldhaus - 素敵な反応、私はそれを取り、それを実行しました:

t() 
{
    e="$( declare -p $1 )"
    eval "declare -A E=${e#*=}"
    declare -p E
}

declare -A A='([a]="1" [b]="2" [c]="3" )'
echo -n original declaration:; declare -p A
echo -n running function tst: 
t A

# Output:
# original declaration:declare -A A='([a]="1" [b]="2" [c]="3" )'
# running function tst:declare -A E='([a]="1" [b]="2" [c]="3" )'
于 2012-06-10T02:51:38.717 に答える
4

連想配列は名前でのみ渡すことができます。

通常の配列も名前で渡す方が良い(より効率的)です。

于 2011-01-11T11:36:09.770 に答える
2

eval echo ...これは、間接化を行うために私が今日思いついた解決策です。

print_assoc_array() {
    local arr_keys="\${!$1[@]}" # \$ means we only substitute the $1
    local arr_val="\${$1[\"\$k\"]}"
    for k in $(eval echo $arr_keys); do #use eval echo to do the next substitution
        printf "%s: %s\n" "$k" "$(eval echo $arr_val)"
    done
}

declare -A my_arr
my_arr[abc]="123"
my_arr[def]="456"
print_assoc_array my_arr

bash 4.3 での出力:

def: 456
abc: 123
于 2016-06-24T18:55:12.263 に答える
-1

史上最高のBashガイドから:

declare -A fullNames
fullNames=( ["lhunath"]="Maarten Billemont" ["greycat"]="Greg Wooledge" )
for user in "${!fullNames[@]}"
do
    echo "User: $user, full name: ${fullNames[$user]}."
done

I think the issue in your case is that $@ is not an associative array: "@: Expands to all the words of all the positional parameters. If double quoted, it expands to a list of all the positional parameters as individual words."

于 2011-09-05T11:51:21.590 に答える