Dereference concatenated variable name
First off, you don't need to use $(echo $FRUITS)
in the for
statement. Using just $FRUITS
is enough. Then you can do away with one of the lines inside the loop, by using eval
.
The eval
simply tells bash to make a second evaluation of the following statement (i.e. one more than its normal evaluation). The \$
survives the first evaluation as $
, and the next evaluation then treats this $
as the start of a variable name, which resolves to "Yellow", etc.
This way you don't need to have a separate step which makes an interim string (which is what I believe was the main intent of your question).
for fruit in $FRUITS ;do
eval echo $fruit is \$${fruit}_COLOUR
done
For an alternative method, as mentioned by Patrick in a comment (above), you can instead use an associative array, in which an element's index does not need to be an integer. You can use a string, such as the name of a type of fruit. Here is an example, using bash's associative array:
# This declares an associative array (It unsets it if it already exists)
declare -A colour
colour['BANANA']="Yellow"
colour["APPLE"]="Green or Red"
colour[MARTIAN ORANGE]="Blue"
for fruit in BANANA APPLE "MARTIAN ORANGE" ;do
echo "$fruit" is "${colour[$fruit]}"
done
You can use the bash-builtin eval
to do that:
#!/bin/bash
FRUITS="BANANA APPLE ORANGE"
BANANA_COLOUR="Yellow"
APPLE_COLOUR="Green or Red"
ORANGE_COLOUR="Blue"
for fruit in $( echo $FRUITS );
do
fruit_colour=${fruit}_COLOUR
eval echo $fruit is \$${fruit_colour}
done
Note the backslashed-dollar sign. Basically, the "eval" line causes bash
to substitue for $fruit
and ${fruit_color}
, then using eval
to do a second round of substition before calling echo
.