15

How do I pass a list to for in bash?

I tried

echo "some
different
lines
" | for i ; do 
  echo do something with $i; 
done

but that doesn't work. I also tried to find an explanation with man but there is no man for

EDIT:

I know, I could use while instead, but I think I once saw a solution with for where they didn't define the variable but could use it inside the loop

rubo77
  • 19,527
  • 31
  • 134
  • 226

4 Answers4

25

for iterates over a list of words, like this:

for i in word1 word2 word3; do echo "$i"; done

use a while read loop to iterate over lines:

echo "some
different
lines" | while read -r line; do echo "$line"; done

Here is some useful reading on reading lines in bash.

Tom Fenech
  • 72,334
  • 12
  • 107
  • 141
  • But i think I once saw a solution with `for` where they didn't define the variable but could use it inside the loop – rubo77 Apr 10 '15 at 11:30
19

This might work but I don't recommend it:

echo "some
different
lines
" | for i in $(cat) ; do
    ...
done

$(cat) will expand everything on stdin but if one of the lines of the echo contains spaces, for will think that's two words. So it might eventually break.

If you want to process a list of words in a loop, this is better:

a=($(echo "some
different
lines
"))
for i in "${a[@]}"; do
    ...
done

Explanation: a=(...) declares an array. $(cmd...) expands to the output of the command. It's still vulnerable for white space but if you quote properly, this can be fixed.

"${a[@]}" expands to a correctly quoted list of elements in the array.

Note: for is a built-in command. Use help for (in bash) instead.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • Thats great, and it is the shortest, and if you wrote the string yourself in that loop you can just use `a="..."` and `for i in $a; do ...` if you know, that there are no "dangerous" signs in it – rubo77 Apr 10 '15 at 12:22
  • 1
    Actually, you should use `a=("word" "a b" "foo")` (3 elements) and then `for i in "${a[@]}"; do ...`; that would iterate three times. You would get 4 iterations. – Aaron Digulla Apr 10 '15 at 12:29
  • But if you don't have spaces and special characters in those lines, you can simply use `$a` as in my example. (My intention is to lazy reformatting and piping stuff on the console to get some things done) – rubo77 Apr 10 '15 at 12:46
  • That's not quite correct. Correct is: If you will never, ever, under no circumstances have spaces ... This is like no one will ever need more than 2 digits to save the year, an attitude which cost a lot of money in 1999. – Aaron Digulla Apr 10 '15 at 13:31
0

This seems to work :

for x in $(echo a b c); do
  echo $x
done
Caduchon
  • 4,574
  • 4
  • 26
  • 67
  • I know. It's an example ! You can also replace $(echo a b c) by $(my command printing some words). Thanks to remove your -1. – Caduchon Apr 12 '15 at 09:04
0

This is not a pipe, but quite similar:

args="some
different
lines";
set -- $args; 
for i ; do 
  echo $i;
done

cause for defaults to $@ if no in seq is given.

maybe you can shorten this a bit somehow?

rubo77
  • 19,527
  • 31
  • 134
  • 226