Bash – calling other variables in a variable name (Bash)

bashshell-scriptvariablevariable substitution

At the moment I have the next paths

langs="EN GE"
dir_EN=/xx
dir_GE=/zz

As you can see the variable $langs has all possible languages in a single array. I would like to save all those paths in a multilingual (dir_ML) array using a loop which checks what the languages are, and then save the corresponding path. Here is what I have so far

for i in $(seq 0 1); do #I used seq because I didn't know how to specify the length of the variable $langs
    dir_ML[$i]=dir_${langs[$i]}
done

The output I am looking for is

dir_ML[0]=/xx

dir_ML[1]=/zz

I hope you can understand what I am trying to do!
Thanks in advance

Best Answer

langs is not an array but a string in your code.

To make it an array and use it:

langs=( EN GE )
dir_EN=/xx
dir_GE=/zz

dir_ml=()
for i in "${langs[@]}"; do
    declare -n p="dir_$i"
    dir_ml+=( "$p" )
done

printf 'dir_ml = "%s"\n' "${dir_ml[@]}"

In the above loop, $i will take the values EN and GE in turn. This also introduces a name reference variable p. When the value of p is accessed, the string that was assigned to the variable when it was declared will be interpreted as a variable name and that variable's value is returned.

The output of the above will be

dir_ml = "/xx"
dir_ml = "/zz"

To use name references in bash, you will need bash version 4.3 or later.


Another (interesting but inferior) possibility:

dir_EN=/xx
dir_GE=/zz

# (can't set dir_ml=() here as its name would be picked up by the loop)
unset dir_ml

for i in "${!dir_@}"; do
    dir_ml+=( "${!i}" )
done

printf 'dir_ml = "%s"\n' "${dir_ml[@]}"

Here, $i will take the values of the variable names dir_EN and dir_GE in turn. We then use variable indirection with ${!i} to get the value of that variable. This variation does not need the langs array, but it instead assumes that no other variable is named dir_-something (which may be considered a bit fragile as a user may easily inject variables with names like these into the script's environment).

The output is the same for this code as for the code above.

Related Question