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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6660010/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 20:45:06  来源:igfitidea点击:

How to rename an associative array in Bash?

bashvariablesassociative-array

提问by David Parks

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).

我需要遍历关联数组并将其内容排空到临时数组(并对值执行一些更新)。

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

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

Sudo code:

须藤代码:

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)

采纳答案by glenn Hymanman

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

回答by Florian Feldhaus

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

回答by tombrus

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

这个单行执行关联数组复制: MAINARRAY=TEMPARRAY

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

回答by Luca Borrione

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

按照glenn Hymanmanffeldhaus的建议,您可以构建一个可能会变得方便的函数:

function cp_hash
{
    local original_hash_name=""
    local copy_hash_name=""

    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

回答by bashly

Here is a small Copy-Function for bash-Variables of any kind
- normal scalar variables
- indexed arrays
- associative arrays

这是任何类型的 bash 变量的小型复制函数
- 普通标量变量
- 索引数组
- 关联数组

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

Usage, Examples:

用法,例子:

# 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>

The results

结果

--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  |  

回答by keen

expanding on Luca Borrione'scp_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 1and 2

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

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  in advance.
        local original_hash_name=""
        local copy_hash_name=""
        #
        # 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

回答by fab

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

回答by Adam Bryzak

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