2016-10-03 49 views
0

在我Korn shell的日子里,我能做到以下几点:制作管道通猛砸逻辑运行在当前shell

#!/bin/ksh 

(
    echo a=1 
    echo b=2 
) | 
    while read line 
    do 
     name=${line%%=*} 
     val=${line#*=} 
     eval "$name=$val" 
     eval "echo $name=\$$name" 
    done 
echo a=$a 
echo b=$b 

输出:

a=1 
b=2 
a=1 
b=2 

含义while循环在前台外壳运行。

但是,当你运行在bash,你会得到:

a=1 
b=2 
a= 
b= 

意思是说在一个子shell中运行。

我知道其他机制,以获得我想要的具体用法,但是,有没有办法使bash在前台运行它像ksh?

+0

查看[BashFAQ#24](http://mywiki.wooledge.org/BashFAQ/024),其中详细介绍了这一点。 –

+0

...这个特定问题的答案也包含在稍微更一般的问题的答案中http://stackoverflow.com/questions/7313491/bash-while-read-resetting-variable-values-using-读取内置在管道中(旁白:mklement0的答案是恕我直言,那里是最好的)。 –

回答

5

bash 4.2引入了lastpipe选项,该选项允许管道中的最后一个命令在当前shell中运行(给定一些基本上适用于非交互式shell的条件)。

shopt -s lastpipe 
x=foo 
echo bar | read x 
echo "$x" # outputs bar, not foo 

在早期版本中,你是有限的解决方法,如进程替换

while read line; do 
... 
done < <(echo a=1; echo b=2) 

和命名管道

mkfifo p 
(echo a=1; echo b=2) > p & 
while read line; do 
... 
done < p 

而且,只是解决了使用的eval这里:

shopt -s lastpipe 
(echo a=1; echo b=2) | 
    while IFS== read -r name value; do 
     IFS= read -r "$name" <<< "$value" 
    done 
+0

谢谢。 好评。我不会使用IFS ==思想,因为它始终可以包含'='符号。 –

+0

这不是问题; 'IFS ==读取名称值<<<“foo = bar = baz”'将'name'设置为'foo'并将'value'设置为'bar = baz'。只有两个参数,'read'只会分开并丢弃第一个'='。我编辑了嵌套的'read'来确保'$ value'的值是逐字使用的。 – chepner

+0

值得使用'read -r'来修正字符串反斜杠的处理。 –