1

Im no bash/shell script expert...what im trying to do the is following: im using array variables as keys to a hashmap. when i iterate over the keys of the hash map i want to evaluate them to the actual array, iterate over the array and print the values in that array out.

arr1=(A B)
arr2=(C D)

declare -A arrmap
arrmap=(
    [arr1]="array 1"
    [arr2]="array 2"
)

for k in "${!arrmap[@]}";
do  
    for f in "${k[@]}";
        do echo "$k: $f";
    done
done

This prints out:

arr2: arr2
arr1: arr1

but what i would like to see is:

A: array 1
B: array 1
C: array 2
D: array 2

EDIT: think i was able to figure it out:

for k in "${!arrmap[@]}"; do  
    eval a=\( \${${k}[@]} \)
    for f in "${a[@]}"; do 
        echo "$k: $f";
    done
done
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
mike01010
  • 5,226
  • 6
  • 44
  • 77

2 Answers2

2

A good rule of thumb is that if you find yourself wanting to use eval, you're doing something wrong. In this case, a nameref is what you need instead.

Documentation for declare -n:

Give each name the nameref attribute, making it a name reference to another variable. That other variable is defined by the value of name. All references, assignments, and attribute modifications to name, except for those using or changing the -n attribute itself, are performed on the variable referenced by name’s value.

#!/usr/bin/env bash

arr1=(A B)
arr2=(C D)

declare -A arrmap=(
    [arr1]="array 1"
    [arr2]="array 2"
)

for k in "${!arrmap[@]}";
do
    declare -n arr="$k"
    for f in "${arr[@]}"; do
        echo "$f: ${arrmap[$k]}"
    done
done

will output

C: array 2
D: array 2
A: array 1
B: array 1

(Order may vary; hash tables don't iterate over elements in a set predictable order)

Shawn
  • 47,241
  • 3
  • 26
  • 60
1

You can use indirect expansion (${!var}) to do what you want without eval:

#! /bin/bash -p

arr1=(A B)
arr2=(C D)

declare -A arrmap
arrmap=(
    [arr1]='array 1'
    [arr2]='array 2'
)

for k in "${!arrmap[@]}"; do  
    ref="$k[@]"
    for f in "${!ref}"; do
        printf "%s: %s\n" "$f" "${arrmap[$k]}"
    done
done
pjh
  • 6,388
  • 2
  • 16
  • 17