我在FreeBSD、GNU/Linux和Solaris下使用不同的shell都遇到了这个问题。这让我头疼了一个多小时,所以我决定在这里发布这个问题。
由于管道的存在,read
命令在它自己的子 shell 中被执行。
echo foo | while read a; do echo $a; done
它将会按照你期望的方式运行。
备选方案:
echo foo | (read a ; echo $a)
编辑:
如果您需要在子shell之外使用$a,则必须反转命令:
read a < <(echo foo); echo $a
这样读操作将在当前进程中执行。
<<<"foo"; echo $a
也可以工作,并且不像 <() 那样产生子shell和命名管道。 - Asfand Qazi我不认为这个已经被提供过:
a=`echo foo`
echo $a
只是提供信息;在ksh中,它按预期工作;另请参阅http://kornshell.com/doc/faq.html,第III节(shell编程问题),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).
lastpipe
选项(使用shopt -s lastpipe
),它将类似地在当前shell而不是子shell中运行管道的最后一个命令。 - Chris Dodd此外,多命令管道中的每个命令都在子shell环境中执行;作为扩展,任何或所有命令都可以在当前环境中执行。所有其他命令将在当前shell环境中执行。
- jlliagre我想出了一种解决方案,它不会在子shell中隐藏变量值,并且可以处理多个值。
set `echo foo bar`
A=$1
B=$2
ls *.c |
while read file
do
echo $a
done
通常情况下没有问题,但是从文件重定向时不一致。
read 命令期望在新行上输入
while read a; do echo $a; done foo bar ^D
大致符合您的要求