I'm used to bash
's builtin read
function in while loops, e.g.:
echo "0 1
1 1
1 2
2 3" |\
while read A B; do
echo $A + $B | bc;
done
I've been working on some make
project, and it became prudent to split files and store intermediary results. As a consequence I often end up shredding single lines into variables. While the following example works pretty well,
head -n1 somefile | while read A B C D E FOO; do [... use vars here ...]; done
it's sort of stupid, because the while loop will never run more than once. But without the while
,
head -n1 somefile | read A B C D E FOO; [... use vars here ...]
The read variables are always empty when I use them. I never noticed this behaviour of read
, because usually I'd use while loops to process many similar lines. How can I use bash
's read
builtin without a while loop? Or is there another (or even better) way to read a single line into multiple (!) variables?
Conclusion
The answers teach us, it's a problem of scoping. The statement
cmd0; cmd1; cmd2 | cmd3; cmd4
is interpreted such that the commands cmd0
, cmd1
, and cmd4
are executed in the same scope, while the commands cmd2
and cmd3
are each given their own subshell, and consequently different scopes. The original shell is the parent of both subshells.
… cmd1; | cmd2 …
is an error. (2) We can tell thatcmd2
andcmd3
are each given their own subshell incmd1; cmd2 | cmd3; cmd4
by trying things likeanswer=42 | sleep 0
orcd other/dir | read foo
. You'll see that the first command in each pipeline must be in a subshell, as they do not effect the main (parent) shell process. – Scott - Слава Україні Feb 12 '15 at 10:27