Lunartist
Lunartist

Reputation: 464

Dynamic array name in bash

Because bash doesn't support "arrays in arrays", I'm trying to dynamize variable name when calling arrays.

bash version : 4.2

I used this expansion method: https://stackoverflow.com/a/18124325/9336478

#!/bin/bash
# data are pre-defined and type is determined later

declare -a data_male
declare -a data_female

data_male=(value1 value2)
data_female=(value3 value4)

type="male" 

for value in ${${!data_$type}[@]};do
  echo $value
done

and it did not work

line 20: ${${!data_$type}[@]} : bad substitution

How do I sort this out?

Upvotes: 3

Views: 1797

Answers (2)

markp-fuso
markp-fuso

Reputation: 34419

If OP can get a newer version of bash installed then a nameref (name reference, available in bash 4.3+) could be used:

declare -a data_male
declare -a data_female

data_male=(value1 value2)
data_female=(value3 value4)

type="male"

declare -n arr="data_${type}"       # dynamically declare arr[] as a name ref to data_male[]

for ndx in "${!arr[@]}"
do
    echo "${arr[${ndx}]}"
done

This generates:

value1
value2

Upvotes: 3

vdavid
vdavid

Reputation: 2544

Unfortunately, in Bash 4.2 you need to eval the array.

printf -v evaluator 'for value in ${%s[@]};do\n  echo $value\ndone' "data_$type"
eval "$evaluator"

printf will inject the name of the array designated by data_$type into the %s part, and then the result of the string is assigned to the variable evaluator.

So, the first part builds a string designed to be evaluated, and then you evaluate it.

Instead of newline characters \n you can also use actual newlines:

printf -v evaluator 'for value in ${%s[@]};do
  echo $value
done' "data_$type"
eval "$evaluator"

You should make sure that the contents of your arrays are safe because this can be used to inject malicious code.

Upvotes: 2

Related Questions