Reputation: 31
I am trying to write a bash script to allow me to choose one array amongst a set of different arrays. For that purpose, I intend so use a simple variable to reference that one array.
#!/bin/bash
#To get all the members of a given array as the output
#variables
FIRST=(A B C D)
SECOND=(planes cars trains bicycles gocarts)
THIRD=(werewolfs vampires zombies ghosts daemons)
FOURTH=(football soccer basketball rugby batmington zumo)
FIFTH=(handguns rifles machineguns bazookas slingshots)
SIXTH=(dogs cats turtles ferrets birds hamsters fish)
SEVENTH=(monday tuesday wednesday thursday friday saturday sunday)
#execution
select ARRAY in "FIRST" "SECOND" "THIRD" "FOURTH" "FIFTH" "SIXTH" "SEVENTH"; do
OUTPUT=eval '"${'${ARRAY}'[@]}"'
echo $OUTPUT
break
done
#end
The above script does not work. So far, I have tried to replace line 9 with these options:
OUTPUT=eval '$'{ARRAY'[@]'}
OUTPUT=eval ${"$ARRAY"[@]}
OUTPUT=eval ${'$ARRAY'[@]}
OUTPUT=eval ${'$'ARRAY[@]}
OUTPUT=eval '$'{"$ARRAY"[@]}
OUTPUT=eval \${${ARRAY}[@]}
What am I missing here?
Upvotes: 3
Views: 230
Reputation: 241771
eval
is absolutely unnecessary to solve this problem. You should always think twice before using eval
because of its fragility. (That is, an error can have disastrous consequences.)
Here's the "traditional" solution, which uses the !
indirection syntax. It's still somewhat fragile, but not as bad as eval
:
select array in "FIRST" "SECOND" "THIRD" "FOURTH" "FIFTH" "SIXTH" "SEVENTH"; do
if [[ $array ]]; then
# Indirection requires the full subscript to be included
# in the variable which is used to indirect. "${!array[@]}"
# would be "0", because that is not indirect syntax; rather it
# is "array keys" syntax.
array_at="$array"[@]
echo "${!array_at}"
break
else
echo "Invalid input; try again" >> /dev/stderr
fi
done
Since bash 4.3, you can use reference declarations, which make the above a little less clunky:
select name in "FIRST" "SECOND" "THIRD" "FOURTH" "FIFTH" "SIXTH" "SEVENTH"; do
if [[ $name ]]; then
declare -n array=name
echo "${array[@]}"
break
else
echo "Invalid input; try again" >> /dev/stderr
fi
done
# Unless the user exits the select by typing an EOF,
# then `array` is now effectively a synonym
# for whichever of the arrays was selected.
Upvotes: 1
Reputation: 31
I got it. The following works for line 9:
OUTPUT=$(eval echo \${${ARRAY}[@]})
Thanks a lot for your patience with this poor little apprentice :)
Upvotes: 0
Reputation: 1548
This worked for me:
#!/bin/bash
#To get all the members of a given array as the output
#variables
FIRST=(A B C D)
SECOND=(planes cars trains bicycles gocarts)
THIRD=(werewolfs vampires zombies ghosts daemons)
FOURTH=(football soccer basketball rugby batmington zumo)
FIFTH=(handguns rifles machineguns bazookas slingshots)
SIXTH=(dogs cats turtles ferrets birds hamsters fish)
SEVENTH=(monday tuesday wednesday thursday friday saturday sunday)
#execution
ARRAY="FIFTH"
select ARRAY in "FIRST" "SECOND" "THIRD" "FOURTH" "FIFTH" "SIXTH" "SEVENTH"; do
eval "OUTPUT=\${$ARRAY[*]}"
echo $OUTPUT
break
done
eval
can be used to introduce new variables. We construct a string that contains the expression assigning the desired value to OUTPUT
and then eval it, thus introducing a new variable OUTPUT
with the desired value.
Upvotes: 1