I am hoping to do something like:
echo 1 2 | read foo bar
To set two new variables, foo and bar, to the values 1 and 2 respectively. (In reality, "echo 1 2" will be an awk / cut invocation for an external data source.)
I am finding that foo and bar do not exist after this line which makes me wonder if it is a scoping issue? I have only used read in while loops and in those cases the loop body was able to access the variables.
Pipes execute in a sub-shell. As such, the variables foo
and bar
are created, 1 and 2 are stored in them, then the subshell exits and you return to the parent shell in which these variables do not exist.
One way to read
into variables as you appear to want is with a "here string"
read foo bar <<<"1 2"
Which will do what you expected the pipe version to do.
This is non-portable, however, and some shells will not support it. You can use the "here document" form instead, which is broadly supported.
$ read foo bar <<EOF
> 1 2
> EOF
Note that EOF
here can be any unique string. A here document will store all lines until one that contains EOF
, or whatever marker you chose, and nothing else. In this case the behavior is also identical with the previous example (but harder to copy and paste and longer to type).
What's going on here?
Both the "here document" and the "here string" are ways to represent text passed to standard input without having to enter it interactively. It is functionally equivalent to just saying read foo bar
, hitting enter, then manually writing 1 2
and hitting enter again.
Instead of pipe, you can do something like this -
[jaypal:~/Temp] exec 3< <(echo "Jaypal Singh")
[jaypal:~/Temp] while read word1 word2 ; do echo "$word1 $word2"; done <&3
Jaypal Singh
[jaypal:~/Temp] exec 3< <(echo "Jaypal Singh")
[jaypal:~/Temp] while read word1 word2 ; do echo "$word1"; done <&3
Jaypal
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With