web-dev-qa-db-ja.com

Bashで連想配列の名前を変更するにはどうすればよいですか?

連想配列をループして、その内容を一時配列に排出する必要があります(そして値の更新を実行します)。

次に、最初の配列の残りの内容を破棄する必要があります。一時配列を元の配列変数に割り当てたいと思います。

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)
16
David Parks

連想配列では、反復する以外の方法はないと思います

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

連想配列をbashで直接コピーすることはできません。おそらく、すでに指摘したように、最善の解決策は、配列を反復処理して段階的にコピーすることです。

変数を関数に渡すために使用した という別の解決策があります。連想配列をコピーするために同じ手法を使用できます。

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

このワンライナーは連想配列のコピーを行います:MAINARRAY = TEMPARRAY

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

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
3
Luca Borrione

これはbash用の小さなコピー関数です-あらゆる種類の変数
-通常のスカラー変数
-インデックス付き配列
-連想配列

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

拡張 Luca Borrione's cp_hash-これは私には機能せず、eval拡張の問題を追跡することを諦めました-bash4.2の前後で違いに遭遇しました。 4.2(何か)以降、これははるかに簡単になります...しかし、それは下位互換性がありません。 1 および 2 を参照してください

したがって、私のバリエーションは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
keen

これはどうですか(実際のコピーは作成せず、ソース変数へのリンクのみを作成します):

#!/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
fab