Consider this example:
cat > test.txt <<EOF
hello world
hello bob
super world
alice worldview
EOF
# using cat to simulate another command output piping;
# get only lines that end with 'world'
fword="world"
for line in "$(cat test.txt | grep " ${fword}\$")"; do
echo "for line: $line"
done
echo "-------"
while read line; do
echo "while line: $line"
done <<< "$(cat test.txt | grep " ${fword}\$")"
The output of this script is:
for line: hello world
super world
-------
while line: hello world
while line: super world
So, basically, the process substitution in the for ... in
loop, ended up being compacted in a single string (with newlines inside) - which for ... in
still sees as a single "entry", and so it loops only once, dumping the entire output.
The while
loop, on the other hand, uses the "classic" here-string - and even with the same quoting of the process substitution (that is, "$(cat test.txt | grep " ${fword}\$")"
), the here-string ends up serving lines one-by-one to the while
, so it loops as expected (twice in this example).
Could anyone explain why this difference happens - and if it is possible to "massage" the formatting of the for .. in
loop, so it also loops correctly like the while
loop?
( It is much easier for me to parse what is going on in the for .. in
syntax, so I'd love to be able to use it, to run through loops like these (built out of results of pipelines and process substitution) - so that is why I'm asking this question. )