Reputation: 9846
In the example function a
, I capture the input from a pipe as follows:
function a() {
if [ -t 1 ]; then
read test
echo "$test"
fi
# If $1 has a value, print it
if [[ -n "$1" ]]; then
echo "$1"
fi
}
called as follows:
echo "hey " | a "hello"
produces the output:
hey
hello
I was inspired by this answer, however a quote after the snippet has me concerned:
But there's no point - your variable assignments may not last! A pipeline may spawn a subshell, where the environment is inherited by value, not by reference. This is why read doesn't bother with input from a pipe - it's undefined.
I'm not sure I understand this - attempting to create subshells yielded the output I expected:
function a() {
(
if [ -t 1 ]; then
read test
echo "$test"
fi
if [[ -n "$1" ]]; then
echo "$1"
fi
)
}
And in the method call:
(echo "hey") | (a "hello")
still yields:
hey
hello
So what is meant by your variable assignments may not last! A pipeline may spawn a subshell, where the environment is inherited by value, not by reference.? Is there something that I've misunderstood?
Upvotes: 1
Views: 359
Reputation: 241671
The quoted note is incorrect. read
doesn't care where its input comes from.
However, you must remember that the variable assigned to by the invocation of the read
command is part of the (sub-)shell which executes the command.
By default, each command executed in a pipeline (a series of commands separated by |
) is executed in a separate subshell. So after you execute echo foo | read foo
, you will find that the value of $foo
has not changed: not because read
ignored its input but rather because the shell read
executed in no longer exists.
Upvotes: 2
Reputation: 23840
Try this:
echo test | read myvar
echo $myvar
You might expect that it will print test
, but it doesn't, it prints nothing. The reason is that bash will execute the read myvar
in a subshell process. The variable will be read, but only in that subshell. So in the original shell the variable will never be set.
On the other hand, if you do this:
echo test | { read myvar; echo $myvar; }
or this
echo test | (read myvar; echo $myvar)
you will get the expected output. This is what happens with your code.
Upvotes: 1