2016-10-03 52 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'來修正字符串反斜槓的處理。 –