In bash, read after a pipe is not setting values
bash
runs the right-hand side of a pipeline in a subshell context, so changes to variables (which is what read
does) are not preserved — they die when the subshell does, at the end of the command.
Instead, you can use process substitution:
$ read a b dump < <(echo 1 2 3 4 5)
$ echo $b $a
2 1
In this case, read
is running within our primary shell, and our output-producing command runs in the subshell. The <(...)
syntax creates a subshell and connects its output to a pipe, which we redirect into the input of read
with the ordinary <
operation. Because read
ran in our main shell the variables are set correctly.
As pointed out in a comment, if your goal is literally to split a string into variables somehow, you can use a here string:
read a b dump <<<"1 2 3 4 5"
I assume there's more to it than that, but this is a better option if there isn't.
This is not a bash
bug as POSIX
allows both bash
and ksh
behaviors, leading to the unfortunate discrepancy you are observing.
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_12
Additionally, each command of a multi-command pipeline is in a subshell environment; as an extension, however, any or all commands in a pipeline may be executed in the current environment. All other commands shall be executed in the current shell environment.
However, with bash 4.2
and newer, you can set the lastpipe
option in non interactive scripts to get the expected result, eg:
#!/bin/bash
echo 1 2 3 4 5 | read a b dump
echo before: $b $a
shopt -s lastpipe
echo 1 2 3 4 5 | read a b dump
echo after: $b $a
Output:
before:
after: 2 1