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

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.

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

  • 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 – little_mice Apr 7 '18 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? – little_mice Apr 7 '18 at 17:17
  • 1
    @little_mice ${!langs[@]} generates the indexes of the array, 0 and 1. The $ is not necessary in arithmetic contexts. – Kusalananda Apr 7 '18 at 17:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.