1

I have $LIST variable that contains few lines and some of the lines has spaces, but I need to take that as one vs two arguments inside of my loop, how would I do that?

\#!/bin/bash

LIST="test1
test 2"

for i in $LIST; do
 echo $i;
done

this will produce me 3 lines, but I want it to produce 2 as test1 on first line and test 2 on second

1
  • 1
    The hashbang is nonconforming and will be ignored, in the best case. It needs to be #!/bin/bash or #! /bin/bash on some ancient UNIXen Commented May 5, 2011 at 14:50

4 Answers 4

5
#!/bin/bash
LIST="test1
test 2"

while read i
do
    echo "[$i]"
done <<< "$LIST"

Thanks to [] characters we can see that the loop was evaluated twice.

Sign up to request clarification or add additional context in comments.

1 Comment

This is a very elegant solution -- I've always resorted to manipulating the IFS. +1
4

IFS controls what's treated as a word break when variables are expanded (e.g. in the for command):

LIST="test1
test 2"

saveIFS="$IFS"; IFS=$'\n'
for i in $LIST; do
    IFS="$saveIFS" # This is only needed if something in the loop depends on IFS
    echo "$i"
done
IFS="$saveIFS"

5 Comments

This works, but if you don't reset the IFS inside the loop, you risk botching seeing weird behavior if a command inside your loop expects the IFS to contain the space and tab characters that they normally do.
@jedwards: True, although IFS doesn't affect that much. If something in the loop does depend on IFS, adding IFS="$saveIFS" to the beginning of the loop will solve this (although, annoyingly, it should still be there after the loop in case $LIST is empty and the loop never executes). On the whole, if you can count on bash extensions, @depesz's answer is probably cleaner.
@Gordon Davidson: Yeah, I'm not sure I encounter it often, but I did once, which made me realize you have to reset it. But you're right, you have to edit it twice inside the loop, as the first command inside the loop body (to the original IFS) and again as the last (to your modified IFS). My general formulation is shown here.
@jedwards: Actually, it's not necessary to re-reset IFS at the end of the loop body. The entire list will be parsed once, before the loop is started, and once that's done IFS can be set back to normal and left that way. I'll edit my answer to show this...
@Gordon: I couldn't get it to work, but I'll give you +1 anyway, maybe its my environment that screw it somehow... thanks, anyway!
0

Just for fun and educational purposes: No need for bashisms like <<< here. Understand that echo keeps newlines in quoted strings and just read line by line as follows:

#!/bin/sh

LIST="test1
test 2"

echo "$LIST" |
while read -r line; do
  echo "[$line]"
done

$ ./x.sh
[test1]
[test 2]

There, 100% POSIX shell compatible!

Comments

-2

No need to change IFS. Just need to quote your variable

LIST="test1
test 2"

for i in "$LIST"; do
 echo "$i";
done

3 Comments

It evaluates the loop once, and not twice. I think that OP wanted the loop evaluated twice.
variable is already in quotes yet that doesn't help at all (thats why i'm here asking you guys & gals)
adding brackets as depesz did shows that this is only evaluated once.

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.