Anton Antonov
Anton Antonov

Reputation: 31

bash dynamically create variables

I am trying to write simple bash script where I need to create dynamically variables. Here is the code

#!/bin//bash
declare -A var12
        var12["a"]=1
        var12["s"]=2
        var12["c"]=3
declare -A var22
        var22["a"]=10
        var22["b"]=20
        var22["c"]=30
declare -A var32
        var32["a"]=100
        var32["b"]=200
        var32["c"]=300
declare -a variables=(12 22 32)
for i in ${variables[@]}
do
        echo $i
        eval currentVar=( \${var$i[@]} )
        echo ${currentVar["a"]} ${currentVar["b"]} ${currentVar["c"]}
done

current output is

12
1 1 1
22
10 10 10
32
100 100 100

I need to be

12
1 2 3
22
10 20 30
32
100 200 300

Were I am wrong

Upvotes: 3

Views: 268

Answers (3)

PesaThe
PesaThe

Reputation: 7499

eval is not the right tool here. You can either use variable indirection:

#!/usr/bin/env bash

declare -A var12=([a]=1 [b]=2 [c]=3)
declare -A var22=([a]=10 [b]=20 [c]=30)
declare -A var32=([a]=100 [b]=200 [c]=300)

declare -a variables=(12 22 32)

for i in "${variables[@]}"; do
    echo "$i"
    current_a="var$i[a]"
    current_b="var$i[b]"
    current_c="var$i[c]"
    echo "${!current_a} ${!current_b} ${!current_c}"
done
# var="arr[@]" -> ${!var} is also possible:
for i in "${variables[@]}"; do
    echo "$i"
    current="var$i[*]"
    echo "${!current}"
done

or you can use nameref (requires bash 4.3 or later):

for i in "${variables[@]}"; do
    declare -n current="var$i"  
    echo "$i"
    echo "${current[a]} ${current[b]} ${current[c]}"
done

or choose a better design, see glennjackman's answer.

Upvotes: 2

glenn jackman
glenn jackman

Reputation: 246774

Don't bother with dynamic variable names. Use an associative array to fake a multidimensional array

declare -A var=(
    [12,a]=1    [12,s]=2    [12,c]=3
    [22,a]=10   [22,s]=20   [22,c]=30
    [32,a]=100  [32,s]=200  [32,c]=300
)
variables=( 12 22 32 )

for i in "${variables[@]}"; do 
    for j in a s c; do 
        printf "%s\t%s\t%s\n" $i $j "${var[$i,$j]}"
    done
done
12      a       1
12      s       2
12      c       3
22      a       10
22      s       20
22      c       30
32      a       100
32      s       200
32      c       300

Upvotes: 2

Jdamian
Jdamian

Reputation: 3115

Your code is wrong for two reasons:

  1. Your currentvar array is not associative -- it is a regular array.

  2. As currentvar is a regular array, the items you put into are arranged using non-negative indices: 0, 1, and so on. Therefore, any expansion of ${currentvar[string]} is actually ${currentvar[0]}, i.e., the first item in the array. Hence, the same repeated value displayed.

Upvotes: 1

Related Questions