0

There are multiple global variables with same pattern in my shell script like:

VALID_DOMESTIC_ANIMAL=(cat dog)
VALID_ACQUATIC_ANIMAL=(shark dolphin)

Now, There is another argument CATAGORY , which could be ACQUATIC/DOMESTIC. How can I select the expected global variable to iterate ? I tried following code:

#!/bin/bash
VALID_DOMESTIC_ANIMAL=(cat dog)
VALID_ACQUATIC_ANIMAL=(shark dolphin)

CATAGORY=ACQUATIC
VALID_CATAGORY_ANIMAL=VALID_${CATAGORY}_ANIMAL
#echo "VALID_CATAGORY_ANIMAL ${VALID_CATAGORY_ANIMAL}"
for anime in "${VALID_CATAGORY_ANIMAL[@]}"; do
    echo "${anime}"
done

I am expecting output shark dolphin but I am getting VALID_ACQUATIC_ANIMAL

How can I tell bash script that if there exists a variable with same name, use it ?

5
  • In recent versions of bash, you should be able to declare VALID_CATAGORY_ANIMAL as a nameref - see this related Q&A from yesterday Varibles - Union Sep 3, 2020 at 12:24
  • Please first debug the script with shellcheck.net
    – Quasímodo
    Sep 3, 2020 at 14:13
  • @Quasímodo updated the loop 'done' Copy paste typo Thanks
    – Aftab Rai
    Sep 3, 2020 at 15:50
  • 1
    Note that: foo=(cat, dog) assigns the values cat, and dog. The comma isn't needed here to separate the two words, but ends up as part of the first word. (Also, "category" and "aquatic".)
    – ilkkachu
    Sep 3, 2020 at 16:18
  • @likkachu , yeah corrected.
    – Aftab Rai
    Sep 7, 2020 at 5:26

2 Answers 2

1

Thanks steeldriver for showing way forward Varibles - Union . I used nameref and it worked for me. Performing following change did the trick.

-VALID_CATAGORY_ANIMAL=VALID_${CATAGORY}_ANIMAL
+declare -n VALID_CATAGORY_ANIMAL=VALID_${CATAGORY}_ANIMAL
0

This may make it clearer. This variable contains the name of another variable. To get its value the shell must first expand the variable name and then the variable value.

for anime in $(eval echo \${$VALID_CATAGORY_ANIMAL[@]}); do

eval - It take an arguments expands variables and passes to execute by the shell
Since we escaped the first dollar sign, the command will go to execution in this:

$(echo ${VALID_ACQUATIC_ANIMAL[@]}

You can insert the following line before the loop

echo $VALID_CATAGORY_ANIMAL    #VALID_ACQUATIC_ANIMAL
echo \${$VALID_CATAGORY_ANIMAL[@]}    #${VALID_ACQUATIC_ANIMAL[@]}
eval echo \${$VALID_CATAGORY_ANIMAL[@]}    #shark, dolphin
2
  • It makes the concept clear. Thanks for it. One followup question: for anime in $(eval echo \${$VALID_CATAGORY_ANIMAL[@]}); do here what is the purpose ofecho ? I understand, eval takes a command as arg. but echo is not really printing anything though.
    – Aftab Rai
    Sep 7, 2020 at 5:18
  • @Aftab_Rai, eval returns a string as command and its arguments for execution in the shell. If there is no command then we get the following: eval hi >bash hi: command not found...
    – nezabudka
    Sep 7, 2020 at 6:53

You must log in to answer this question.

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