2013-10-24 51 views
46

猛砸允許使用:cat <(echo "$FILECONTENT")如何管道輸入到猛砸while循環後循環和保持變量結束

擊還允許使用:while read i; do echo $i; done </etc/passwd

結合前兩本可用於:echo $FILECONTENT | while read i; do echo $i; done

最後一個問題是它創建了子shell,並且在while循環結束變量i之後無法再訪問。

我的問題是:

如何實現這樣的事情:while read i; do echo $i; done <(echo "$FILECONTENT")或者換句話說:我怎樣才能確保i倖存while循環?

請注意,我知道封閉while語句爲{},但這並不解決問題(假設你想使用while循環的功能和返回i變量)

+0

http://mywiki.wooledge.org/BashFAQ/024 – tripleee

+0

相關:https://stackoverflow.com/questions/37229058/append-to-an-array-variable-from-a-pipeline-command。解釋所有選項,包括下面提到的過程替換和'lastpipe'及其優缺點。 –

+0

相關:[一個在while循環中修改的變量不會被記住](https://stackoverflow.com/questions/16854280/a-variable-modified-inside-a-while-loop-is-not-remembered)。 – codeforester

回答

60

Process Substitution正確的符號是:

while read i; do echo $i; done < <(echo "$FILECONTENT") 

當循環終止時,在循環中分配的最後一個值爲i。 另一種方法是:

echo $FILECONTENT | 
{ 
while read i; do echo $i; done 
...do other things using $i here... 
} 

該括號是一個I/O分組操作和本身不創建一個子shell。在這種情況下,它們是流水線的一部分,因此作爲子外殼運行,但這是因爲|而不是{ ... }。你在問題中提到這一點。 AFAIK,你可以在這些函數內做一個返回。


猛砸還提供了shopt內置和它的許多選項之一是:

lastpipe

如果設置和作業控制不活動,外殼運行的最後一個命令管道沒有在當前shell環境的後臺執行。

因此,在腳本使用這樣的事情使循環之後可用的modfied sum

FILECONTENT="12 Name 
13 Number 
14 Information" 
shopt -s lastpipe # Comment this out to see the alternative behaviour 
sum=0 
echo "$FILECONTENT" | 
while read number name; do ((sum+=$number)); done 
echo $sum 

在命令行中執行此操作通常運行的犯規「作業控制是不活躍」 (即在命令行中,作業控制處於活動狀態)。不使用腳本進行測試失敗。

此外,由Gareth Rees在他answer指出,有時你可以使用一個here string

while read i; do echo $i; done <<< "$FILECONTENT" 

這並不需要shopt;您可以使用它來保存進程。

+0

請原諒我的無知。我知道這是正確的解決方案,我已經標記爲答案,所以它爲我工作。但是現在,當我讀'我讀的時候,做echo $ i;完成<<(cat/etc/passwd); echo $ i'它沒有返回最後一行兩次。我做錯了什麼? –

+0

@WakanTanka:我不得不嘗試一下......我相信答案是,失敗的讀取將'i'重置爲空,所以循環後的回聲迴響一個空行。 –

+0

過程替代參考的榮譽。我沒有意識到。 – Atcold