Search code examples
bashassociative-arraydeclare

associative array initialization via string and without declare


I want to have a global associative array, that is filled at several locations and I can not get it to work to initialize the array with the content of a string without using the declare -A -g over and over at said locations(which I don't feel like is the smartest approach). I've extracted the issue to the code below:

#!/bin/bash

declare -A arr
declare inputString

inputString="([key]=val)"

arr="$inputString"
printf "from variable: ${arr[*]}\n"
printf "from variable: ${arr[key]}\n"

arr=([key]=val)
printf "inline: ${arr[*]}\n"
printf "inline: ${arr[key]}\n"

declare -A arr=$inputString
printf "with declare: ${arr[*]}\n"
printf "with declare: ${arr[key]}\n"

the output is:

from variable: ([key]=val)
from variable: 
inline: val
inline: val
with declare: val
with declare: val

whereas I would expect it to be:

from variable: val
from variable: val
inline: val
inline: val
with declare: val
with declare: val

what do I have to do to accomplish this task?


Solution

  • One bash 4.3+ approach using a nameref:

    myadd() {                             # $1 == array name; $2 == key name; $3 == value
        declare -n _arr="$1"              # nameref
        _arr+=(["$2"]="$3")
    }
    
    myclear() {
        declare -n _arr="$1"
        _arr=()
    }
    

    Taking for a test drive:

    unset      arr1 arr2
    declare -A arr1 arr2
    
    myadd arr1 keyX 3
    myadd arr1 Index_45 16
    myadd arr2 long_string_abc long_value_xyz
    
    typeset -p arr1 arr2
        ==> declare -A arr1=([keyX]="3" [Index_45]="16" )
        ==> declare -A arr2=([long_string_abc]="long_value_xyz" )
    
    myclear arr1
    
    myadd arr1 aaa 111
    myadd arr1 bbb 222
    
    typeset -p arr1
        ==> declare -A arr1=([bbb]="222" [aaa]="111" )