Iterating over bash arrays, submenu of array name dynamically, is this possible?

I have a script that iterates over an array of values, something like this (omitted for the purpose of this question):

COUNTRIES=( ENGLAND SCOTLAND WALES )

for i in ${COUNTRIES[@]}
do                  
    echo "Country is $i "
done

My question is: is it possible to replace the array dynamically? For example, I want to be able to pass an iteration in an array at runtime. I tried the following, but I think my syntax might be wrong

COUNTRIES=( ENGLAND SCOTLAND WALES )
ANIMALS=( COW SHEEP DOG )

loopOverSomething()
{
    for i in ${$1[@]}
    do                  
        echo "value is $i "
    done
}

loopOverSomething $ANIMALS

I get line 22: ${$2[@]}: bad substitution

+5
source share
3 answers

You can use the indirect bash extension to do this:

loopOverSomething()
{
    looparray="$1[@]"
    for i in "${!looparray}"
    do
        echo "value is $i"
    done
}
+4
source

You can use an array as an argument as follows:

COUNTRIES=( ENGLAND SCOTLAND "NEW WALES" )
ANIMALS=( COW SHEEP DOG )

loopOverSomething()
{
    for i in "$@"
    do                  
        echo "value is $i "
    done
}

loopOverSomething "${ANIMALS[@]}"
loopOverSomething "${COUNTRIES[@]}"
0
source

BashFAQ # 006:

We are not aware of any trick that could duplicate this functionality in POSIX or Bourne shells (with the exception of using eval, which is extremely difficult to do safely). Bash can almost do this - some tricks with an indirect array work, while others do not, and we don’t know if the syntax will remain stable in future releases. So, think about it using your risk.

# Bash -- trick #1.  Seems to work in bash 2 and up.
realarray=(...) ref=realarray; index=2
tmp="$ref[$index]"
echo "${!tmp}"            # gives array element [2]

# Bash -- trick #2.  Seems to work in bash 3 and up.
# Does NOT work in bash 2.05b.
tmp="$ref[@]"
printf "<%s> " "${!tmp}"; echo    # Iterate whole array.
0
source

All Articles