如何将关联数组作为参数传递给Bash中的函数?

nik*_*fly 36 arrays bash associative-array associative

如何将关联数组作为参数传递给函数?这在巴什有可能吗?

以下代码未按预期工作:

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

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

done

}
Run Code Online (Sandbox Code Playgroud)

将关联数组传递给像普通数组这样的函数不起作用:

iterateArray "$A_DATA"
Run Code Online (Sandbox Code Playgroud)

要么

iterateArray "$A_DATA[@]"
Run Code Online (Sandbox Code Playgroud)

Flo*_*aus 40

上周我遇到了完全相同的问题并且考虑了很长一段时间.

看来,无法对关联数组进行序列化或复制.关联数组有一个很好的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)" 
Run Code Online (Sandbox Code Playgroud)

  • 我无法让这个工作,显然因为**Bash 4.3**有`declare -n`.请参阅另一个主题:http://stackoverflow.com/a/30894167/4162356. (4认同)
  • 扩展“${1#*=}”周围的双引号可以修复空格问题。也就是说,这对于任意输入来说根本不安全。它*需要*来自“declare -p”,否则它允许任意代码执行。传名版本更安全。 (2认同)
  • 我永远不会使用 eval。 (2认同)

lin*_*ing 12

基于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" 
Run Code Online (Sandbox Code Playgroud)

输出将是:

doo: 456
pou: 789
mail: ab\npo
Run Code Online (Sandbox Code Playgroud)


Orw*_*ile 7

更新,完全回答这个问题,这是我的图书馆的一小部分:

通过引用迭代关联数组

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
Run Code Online (Sandbox Code Playgroud)

这是我早期工作的开发,我将在下面留下.

@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" )'
Run Code Online (Sandbox Code Playgroud)


Tod*_*man 6

如果您使用的是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
Run Code Online (Sandbox Code Playgroud)

您不必使用_ref后缀。这就是我在这里选择的 只要引用与原始变量名称不同即可,您可以调用该引用(否则将收到“循环名称引用”错误)。

  • 如何将关联数组传递给另一个脚本? (4认同)
  • 太感谢了。这一定是处理 AA 的最简单的方法。你让我免去了很多焦虑。 (2认同)
  • 现在这很有趣!我从未尝试过,因为参考手册似乎说相反:“nameref 属性不能应用于数组变量。” 在 https://www.gnu.org/software/bash/manual/bash.html 但正如伽利略所说......“然而它......适用于数组!” (2认同)

aks*_*aks 4

您只能按名称传递关联数组。

最好(更有效)也按名称传递常规数组。

  • 您可以在函数中执行类似 `eval echo "\${$1[$key]}"` 的操作,并传入变量名称,不带 `$`。 (3认同)