Jimmy
Jimmy

Reputation: 16428

Iterate over bash arrays, substitute array name dynamically, is this possible?

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

COUNTRIES=( ENGLAND SCOTLAND WALES )

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

My question is, is it possible to substitute the array dynamically? For example, I want to be able to pass in the array to iterate over at runtime. I've 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'm getting line 22: ${$2[@]}: bad substitution

Upvotes: 5

Views: 3926

Answers (3)

Gordon Davisson
Gordon Davisson

Reputation: 125788

You can use bash's indirect expansion for this:

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

Upvotes: 4

sgibb
sgibb

Reputation: 25736

You could use the array as argument in the following way:

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

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

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

Upvotes: 0

Charles Duffy
Charles Duffy

Reputation: 295403

This is covered by BashFAQ #006:

We are not aware of any trick that can duplicate that functionality in POSIX or Bourne shells (short of using eval, which is extremely difficult to do securely). Bash can almost do it -- some indirect array tricks work, and others do not, and we do not know whether the syntax involved will remain stable in future releases. So, consider this a use at your own risk hack.

# 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.

Upvotes: 0

Related Questions