7

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

2 Answers 2

10

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.

0
6

This can be accomplished as follows:

#!/bin/bash
langs=(EN GE)
dir_EN=/xx
dir_GE=/zz

for i in ${!langs[@]}; do
        temp="dir_${langs[i]}"
        dir_ML[i]=${!temp}
done

First I have changed langs="EN GE" to langs=(EN GE) because this needs to be an array.

I have also changed $(seq 0 1) to ${!langs[@]} which will expand to the index (or name in the case of an associative array) of each item in the array. So in this example 0 1.

Then I set a temp variable to dir_${langs[i]} (dir_EN and dir_GE).

Then using the ! parameter expansion I expand the variable with that name to set the element of dir_ML

3
  • Thank you so much for your answer. You know? I still have a question. Could you explain to me why you used ${!langs[@]} instead of ${langs[@]} (without the question mark) I got confused with that Commented Apr 7, 2018 at 17:13
  • And also, I would like ask you why in the second line of the loop it is not necessary to use "$" before the i. Shouldn't it be used since it is a variable? Commented Apr 7, 2018 at 17:17
  • 1
    @little_mice ${!langs[@]} generates the indexes of the array, 0 and 1. The $ is not necessary in arithmetic contexts.
    – Kusalananda
    Commented Apr 7, 2018 at 17:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .