Bash:如何将关联数组分配给另一个变量名(例如,重命名变量)?

时间:2022-05-03 12:17:40

I need to loop over an associative array and drain the contents of it to a temp array (and perform some update to the value).

我需要对关联数组进行循环,并将其内容排入temp数组中(并对值执行一些更新)。

The leftover contents of the first array should then be discarded and i want to assign the temp array to the original array variable.

第一个数组的剩余内容应该被丢弃,我想将temp数组分配给原始数组变量。

Sudo code:

Sudo代码:

declare -A MAINARRAY
declare -A TEMPARRAY
... populate ${MAINARRAY[...]} ...

while something; do     #Drain some values from MAINARRAY to TEMPARRAY
    ${TEMPARRAY["$name"]}=((${MAINARRAY["$name"]} + $somevalue))
done
... other manipulations to TEMPARRAY ...

unset MAINARRAY        #discard left over values that had no update
declare -A MAINARRAY
MAINARRAY=${TEMPARRAY[@]}  #assign updated TEMPARRAY back to MAINARRAY (ERROR HERE)

7 个解决方案

#1


12  

With associative arrays, I don't believe there's any other method than iterating

有了关联数组,我不相信还有其他方法可以迭代。

for key in "${!TEMPARRAY[@]}"  # make sure you include the quotes there
do
  MAINARRAY["$key"]="${TEMPARRAY["$key"]}"
  # or: MAINARRAY+=( ["$key"]="${TEMPARRAY["$key"]}" )
done

#2


17  

Copying associative arrays is not directly possible in bash. The best solution probably is, as already been pointed out, to iterate through the array and copy it step by step.

在bash中不能直接复制关联数组。正如已经指出的那样,最好的解决方案可能是遍历数组并一步一步地复制它。

There is another solution which I used to pass variables to functions. You could use the same technique for copying associative arrays:

还有另一种方法,我把变量传递给函数。您可以使用相同的技术来复制关联数组:

# declare associative array
declare -A assoc_array=(["key1"]="value1" ["key2"]="value2")
# convert associative array to string
assoc_array_string=$(declare -p assoc_array)
# create new associative array from string
eval "declare -A new_assoc_array="${assoc_array_string#*=}
# show array definition
declare -p new_assoc_array

#3


6  

This one-liner does an associative array copy: MAINARRAY=TEMPARRAY

这个一行程序执行一个关联数组复制:MAINARRAY=TEMPARRAY。

eval $(typeset -A -p TEMPARRAY|sed 's/ TEMPARRAY=/ MAINARRAY=/')

#4


1  

Following both the suggestions of glenn jackman and ffeldhaus, you can build a function which might become handy:

根据glenn jackman和ffeldhaus的建议,你可以构建一个功能,它可能变得方便:

function cp_hash
{
    local original_hash_name="$1"
    local copy_hash_name="$2"

    local __copy__=$(declare -p $original_hash_name);
    eval declare -A __copy__="${__copy__:$(expr index "${__copy__}" =)}";

    for i in "${!__copy__[@]}"
    do
        eval ${copy_hash_name}[$i]=${__copy__[$i]}
    done
}


Usage:

用法:

declare -A copy_hash_name
cp_hash 'original_hash_name' 'copy_hash_name'


Example:

例子:

declare -A hash
hash[hello]=world
hash[ab]=cd

declare -A copy
cp_hash 'hash' 'copy'

for i in "${!copy[@]}"
do
    echo "key  : $i | value: ${copy[$i]}"
done


Will output

将输出

key  : ab | value: cd
key  : hello | value: world

#5


0  

expanding on Luca Borrione's cp_hash - which didn't work for me, and I gave up trying to track down the eval expansion issue - I ran into differences before and after bash 4.2. after 4.2(something) this gets a lot easier... but that's not backwards compatible. See 1 and 2

扩展了Luca Borrione的cp_hash——这对我没用,我放弃了跟踪eval扩展的问题——在bash 4.2之前和之后都遇到了差异。在4.2(某物)之后,这变得容易得多…但这不是向后兼容的。看到1和2

so my variation tested on 4.1.2(1) and 4.3.46(1):

所以我的变化测试在4.1.2(1)和4.3.46(1):

#!/bin/bash
## bash4 due to associative arrays!

    function cp_hash() {
        ## REQUIRES you to declare -A $2 in advance.
        local original_hash_name="$1"
        local copy_hash_name="$2"
        #
        # sadly we have no way to identify if you have already declared it, so bull ahead.
        #
        ## store the definition of the old array
        local __copy__=$(declare -p $original_hash_name)
        ## rename the array inside the definition
        __copy__=${__copy__/${original_hash_name}=/__copy__=}

        ## for bash 4.2 > we could end here.
        ## declare -A creates local scope variables by default, so add -g
        ## this DOES NOT work prior to 4.2, even w/o -g and w/ a declare outside.
        #    __copy__=${__copy__/${original_hash_name}=/${copy_hash_name}=}
        #    eval ${__copy__/-A/-g -A}

        ## for bash4 where we can't do -g, then:
        ## local associative array based on the definition we stored and modified
        eval ${__copy__}
        ## loop through the local copy, and store it in the declared-outside copy.
        for i in "${!__copy__[@]}"
        do
            eval ${copy_hash_name}[$i]=${__copy__[$i]}
        done
    }

    declare -A hash
    hash[hello]=world
    hash[ab]=cd

    #not required for 4.2+ if you use -g, neither helps nor hinders
    declare -A copy

    cp_hash 'hash' 'copy'

    echo hash: ${hash[@]}
    echo copy: ${copy[@]}

    echo "copy result loop"
    for i in "${!copy[@]}"
    do
        echo "key  : $i | value: ${copy[$i]}"
    done

#6


0  

How about this one (Doesn't create a real copy, just a link to source variable):

这个(不创建一个真正的拷贝,只是一个链接到源变量):

#!/bin/bash
declare -A my_array=(["key1"]="value1" ["key2"]="value2")
declare -n arr=my_array
arr['LOG_FILE']=/tmp/log.txt
echo ${arr['key1']}
echo ${arr['LOG_FILE']}

Will print:

将打印:

value1
/tmp/log.txt

#7


-1  

MAINARRAY=( "${TEMPARRAY[@]}" )

#1


12  

With associative arrays, I don't believe there's any other method than iterating

有了关联数组,我不相信还有其他方法可以迭代。

for key in "${!TEMPARRAY[@]}"  # make sure you include the quotes there
do
  MAINARRAY["$key"]="${TEMPARRAY["$key"]}"
  # or: MAINARRAY+=( ["$key"]="${TEMPARRAY["$key"]}" )
done

#2


17  

Copying associative arrays is not directly possible in bash. The best solution probably is, as already been pointed out, to iterate through the array and copy it step by step.

在bash中不能直接复制关联数组。正如已经指出的那样,最好的解决方案可能是遍历数组并一步一步地复制它。

There is another solution which I used to pass variables to functions. You could use the same technique for copying associative arrays:

还有另一种方法,我把变量传递给函数。您可以使用相同的技术来复制关联数组:

# declare associative array
declare -A assoc_array=(["key1"]="value1" ["key2"]="value2")
# convert associative array to string
assoc_array_string=$(declare -p assoc_array)
# create new associative array from string
eval "declare -A new_assoc_array="${assoc_array_string#*=}
# show array definition
declare -p new_assoc_array

#3


6  

This one-liner does an associative array copy: MAINARRAY=TEMPARRAY

这个一行程序执行一个关联数组复制:MAINARRAY=TEMPARRAY。

eval $(typeset -A -p TEMPARRAY|sed 's/ TEMPARRAY=/ MAINARRAY=/')

#4


1  

Following both the suggestions of glenn jackman and ffeldhaus, you can build a function which might become handy:

根据glenn jackman和ffeldhaus的建议,你可以构建一个功能,它可能变得方便:

function cp_hash
{
    local original_hash_name="$1"
    local copy_hash_name="$2"

    local __copy__=$(declare -p $original_hash_name);
    eval declare -A __copy__="${__copy__:$(expr index "${__copy__}" =)}";

    for i in "${!__copy__[@]}"
    do
        eval ${copy_hash_name}[$i]=${__copy__[$i]}
    done
}


Usage:

用法:

declare -A copy_hash_name
cp_hash 'original_hash_name' 'copy_hash_name'


Example:

例子:

declare -A hash
hash[hello]=world
hash[ab]=cd

declare -A copy
cp_hash 'hash' 'copy'

for i in "${!copy[@]}"
do
    echo "key  : $i | value: ${copy[$i]}"
done


Will output

将输出

key  : ab | value: cd
key  : hello | value: world

#5


0  

expanding on Luca Borrione's cp_hash - which didn't work for me, and I gave up trying to track down the eval expansion issue - I ran into differences before and after bash 4.2. after 4.2(something) this gets a lot easier... but that's not backwards compatible. See 1 and 2

扩展了Luca Borrione的cp_hash——这对我没用,我放弃了跟踪eval扩展的问题——在bash 4.2之前和之后都遇到了差异。在4.2(某物)之后,这变得容易得多…但这不是向后兼容的。看到1和2

so my variation tested on 4.1.2(1) and 4.3.46(1):

所以我的变化测试在4.1.2(1)和4.3.46(1):

#!/bin/bash
## bash4 due to associative arrays!

    function cp_hash() {
        ## REQUIRES you to declare -A $2 in advance.
        local original_hash_name="$1"
        local copy_hash_name="$2"
        #
        # sadly we have no way to identify if you have already declared it, so bull ahead.
        #
        ## store the definition of the old array
        local __copy__=$(declare -p $original_hash_name)
        ## rename the array inside the definition
        __copy__=${__copy__/${original_hash_name}=/__copy__=}

        ## for bash 4.2 > we could end here.
        ## declare -A creates local scope variables by default, so add -g
        ## this DOES NOT work prior to 4.2, even w/o -g and w/ a declare outside.
        #    __copy__=${__copy__/${original_hash_name}=/${copy_hash_name}=}
        #    eval ${__copy__/-A/-g -A}

        ## for bash4 where we can't do -g, then:
        ## local associative array based on the definition we stored and modified
        eval ${__copy__}
        ## loop through the local copy, and store it in the declared-outside copy.
        for i in "${!__copy__[@]}"
        do
            eval ${copy_hash_name}[$i]=${__copy__[$i]}
        done
    }

    declare -A hash
    hash[hello]=world
    hash[ab]=cd

    #not required for 4.2+ if you use -g, neither helps nor hinders
    declare -A copy

    cp_hash 'hash' 'copy'

    echo hash: ${hash[@]}
    echo copy: ${copy[@]}

    echo "copy result loop"
    for i in "${!copy[@]}"
    do
        echo "key  : $i | value: ${copy[$i]}"
    done

#6


0  

How about this one (Doesn't create a real copy, just a link to source variable):

这个(不创建一个真正的拷贝,只是一个链接到源变量):

#!/bin/bash
declare -A my_array=(["key1"]="value1" ["key2"]="value2")
declare -n arr=my_array
arr['LOG_FILE']=/tmp/log.txt
echo ${arr['key1']}
echo ${arr['LOG_FILE']}

Will print:

将打印:

value1
/tmp/log.txt

#7


-1  

MAINARRAY=( "${TEMPARRAY[@]}" )