如何在Bash中重命名关联数组?

问题描述 投票:16回答:8

我需要循环一个关联数组并将其内容排放到临时数组(并对该值执行一些更新)。

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

伪代码:

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)
bash variables associative-array
8个回答
12
投票

使用关联数组,我不相信除了迭代之外还有其他任何方法

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

23
投票

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

I used to pass variables to functions还有另一个解决方案。您可以使用相同的技术来复制关联数组:

# 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

7
投票

这个单行做一个关联数组副本:MAINARRAY = TEMPARRAY

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

2
投票

根据glenn jackmanffeldhaus的建议,你可以建立一个可能变得方便的功能:

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
}

用法:

declare -A copy_hash_name
cp_hash 'original_hash_name' 'copy_hash_name'

例:

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

会输出

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

1
投票

扩展Luca Borrione's cp_hash - 这对我不起作用,我放弃了试图追踪eval扩展问题 - 我在bash 4.2之前和之后遇到了差异。在4.2(某些东西)之后,这变得容易多了......但这并不是向后兼容的。见12

所以我的变异测试了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

1
投票

这个怎么样(不创建真正的副本,只是源变量的链接):

#!/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']}

将打印:

value1
/tmp/log.txt

1
投票

这是一个用于任何类型的bash-Variables的小型复制函数 - 正常的标量变量 - 索引数组 - 关联数组

### Function vcp    -VariableCoPy-  
# $1 Name of existing Source-Variable  
# $2 Name for the Copy-Target  
vcp() {
    local var=$(declare -p $1)
    var=${var/declare /declare -g }
    eval "${var/$1=/$2=}"
}

用法,示例:

# declarations
var="  345  89  "
ind_array=(Betty "  345  89  ")
declare -A asso_array=([one]=Harry [two]=Betty [some_signs]=" +*.<\$~,'/ ")  

# produce the copy
vcp var varcopy
vcp ind_array ind_array_copied
vcp asso_array asso_array_2   

# now you can check the equality between original and copy with commands like
# declare -p <name>

结果

--3    1: "${asso_array[@]}"   
(5)       asso_array[one]:        |Harry|   
(11)      asso_array[some_signs]: | +*.<$~,'/ |   
(5)       asso_array[two]:        |Betty|   
--3    4: "${asso_array_2[@]}"   
(5)       asso_array_2[one]:        |Harry|   
(11)      asso_array_2[some_signs]: | +*.<$~,'/ |   
(5)       asso_array_2[two]:        |Betty|   
--2    7: "${ind_array[@]}"   
(5)       ind_array[0]:   |Betty|   
(11)      ind_array[1]:   |  345  89  |   
--2    9: "${ind_array_copied[@]}"   
(5)       ind_array_copied[0]:   |Betty|   
(11)      ind_array_copied[1]:   |  345  89  |   
(11)  11: "$var":   |  345  89  |  
(11)  12: "$varcopy":   |  345  89  |  

-2
投票
MAINARRAY=( "${TEMPARRAY[@]}" )
© www.soinside.com 2019 - 2024. All rights reserved.