[ACCEPTED]-Why is "echo foo | read a ; echo $a" not working as expected?-shell

Accepted answer
Score: 15

Due to the piping the read is executed in its 2 own subshell.

echo foo | while read a; do echo $a; done

will do what you expect it 1 to.

Score: 7


echo foo | (read a ; echo $a)


If you need $a outside 3 the subshell, you have to reverse the commands:

read a < <(echo foo); echo $a

this 2 way the read is executed in the current 1 process

Score: 3

I don't think this one has already been 1 given:

a=`echo foo`
echo $a
Score: 3

Just FYI; in ksh it is working as expected; See 1 also http://kornshell.com/doc/faq.html, Section III (shell programming questions), Q13:

Q13.    What is $bar after, echo foo | read bar?
A13.    The is foo.  ksh runs the last component of a pipeline
        in the current process.  Some shells run it as a subshell
        as if you had invoked it as  echo foo | (read bar).
Score: 1

The | is an inter-process communications operator. So, implicitly, there 25 is a subprocess that must be created to 24 parse and evaluate the expression on one 23 side of it or the other. Bash, and older 22 Bourne shells create a subprocess to the 21 right of the operator (reading from the 20 pipe) which means that any variables set 19 there are only in scope until that process 18 exits (which is at the semicolon in this 17 code example.

zsh and newer versions of Korn 16 shell (at least from '93 on, but possibly 15 even as far back as ksh '88) will create the 14 subprocess on the other side of the pipe 13 (writing into it). Thus they will work 12 in the way that the author of this question 11 intends. ("As expected" is, of course, highly 10 subjective. Understanding the nature of 9 the pipe should lead one to expect this 8 to behave in an implementation specific 7 manner).

I don't know if there is any specific 6 provision in Posix or Spec 1170 or SuS or 5 any other published standard that requires 4 one or the other semantics. However, in 3 practice it's clear that you must not depend 2 on the behavior; though you can easily test 1 for it within your scripts.

Score: 0

I came up with a solution that doesn't hide 2 the variable values in a subshell, and that 1 can also work with multiple values.

set `echo foo bar`

More Related questions