tags:

views:

2059

answers:

4

In perl one would simply do the following to store and iterate over a list of names

my @fruit = (apple, orange, kiwi);
foreach (@fruit) {
        print $_;
}

What would the equivalent be in bash?

+1  A: 
for i in apple orange kiwi
do
  echo $i
done
JBB
+1  A: 

Like this:

FRUITS="apple orange kiwi"
for FRUIT in $FRUITS; do
  echo $FRUIT
done

Notice this won't work if there are spaces in the names of your fruits. In that case, see this answer instead, which is slightly less portable but much more robust.

emk
In Bash on Mac OS X, I appear to need either a semi-colon or line break before the 'do'.
emk
Yes, you do need the semi-colon unless your "do" is on a new line. Also, $IFS must contain a space for this to work.
Chris Jester-Young
depending on IFS during iteration (rather than just assignment) is bad juju, making this answer suboptimal. Granted, mine did too -- I was testing on zsh, fixed for bash since.
Charles Duffy
+3  A: 

Now that the answer I like has been accepted as the correct answer, I'll now move into another topic: how to use IFS for personal gain. :-P

fruits="apple,orange,kiwifruit,dried mango"
(IFS=,
 for fruit in $fruits; do
     echo "$fruit"
 done)

I've put the code in brackets so that the IFS change is isolated into its own subprocess; thus at the end of the bracketed section, IFS is reverted back to its old value. :-)

Chris Jester-Young
When I try `fruits=(apple orange "kiwi fruit")`, bash splits "kiwi" and "fruit" into separate entities during the loop. As long as you for/in, you'll get burned by the IFS. But `echo ${fruits[2]}` does the right thing, which is nice.
emk
See http://stackoverflow.com/questions/78592/what-is-a-good-equivalent-to-perl-lists-in-bash#78631 for a version of this code which works.
emk
Thanks for feedback! Fixed.
Chris Jester-Young
+10  A: 

bash (unlike POSIX sh) supports arrays:

fruits=(apple orange kiwi "dried mango")
for fruit in "${fruits[@]}"; do
  echo "${fruit}"
done

This has the advantage that array elements may contain spaces or other members of $IFS; as long as they were correctly inserted as separate elements, they are read out the same way.

Charles Duffy
I'm also seeing "dried" and "mango" printing as separate fruits here, using bash on Debian and Mac OS X. So this doesn't seem to protect against the IFS for me. :-(
emk
emk, that's my bad -- I was testing on zsh, not bash; fixed it since.
Charles Duffy
I can confirm that this works.
emk