Why is “echo foo | read a ; echo $a” not working a

2019-03-13 18:10发布

I could replicate the problem with various shells under FreeBSD, GNU/Linux, and Solaris. It had me head-scratching for more than an hour, so I decided to post the question here.

标签: linux unix shell
8条回答
地球回转人心会变
2楼-- · 2019-03-13 18:10

alternative:

echo foo | (read a ; echo $a)

Edit:

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

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

this way the read is executed in the current process

查看更多
三岁会撩人
3楼-- · 2019-03-13 18:10

Just FYI; in ksh it is working as expected; See 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).
查看更多
欢心
4楼-- · 2019-03-13 18:14

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

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

will do what you expect it to.

查看更多
霸刀☆藐视天下
5楼-- · 2019-03-13 18:17

read expects input on a new line

while read a; do echo $a; done
foo
bar
^D

is more or less what you wanted

查看更多
老娘就宠你
6楼-- · 2019-03-13 18:21

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

a=`echo foo`
echo $a
查看更多
一夜七次
7楼-- · 2019-03-13 18:21

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

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

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

查看更多
登录 后发表回答