5

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

1
  • 1
    +1 for well stated and focused problem, sample code AND error messages included. Good luck. Commented May 17, 2012 at 14:40

3 Answers 3

4

You can use bash's indirect expansion for this:

loopOverSomething()
{
    looparray="$1[@]"
    for i in "${!looparray}"
    do
        echo "value is $i"
    done
}
Sign up to request clarification or add additional context in comments.

2 Comments

Did you test this? It certainly doesn't work exactly as-given, and the BashFAQ entry on the subject indicates that it won't.
I tested it... and then made a copy-paste error when I posted it. Should be fixed now.
0

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.

Comments

0

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[@]}"

1 Comment

-1 for not using quotes -- if countries=( "New Wales" England ), "New" and "Wales" would be treated as separate entries.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.