2012-01-17 24 views
4

這些做工精細,做他們應該(打印文件foo的內容):的bash/zsh中輸入進程替換給出與結合語法錯誤而

cat <foo 
while read line; do echo $line; done <foo 
cat <(cat foo) 

但是這給了我在zsh的語法錯誤:

zsh$ while read line; do echo $line; done <(cat foo) 
zsh: parse error near `<(cat foo)' 

和bash:

bash$ while read line; do echo $line; done <(cat foo) 
bash: syntax error near unexpected token `<(cat foo)' 

有誰知道原因,也許一個解決方法嗎?

注:這顯然是一個玩具的例子。在實際的代碼,我需要while循環體在主shell進程執行,因此,我不能只用

cat foo | while read line; do echo $line; done 

回答

6

你需要的進程替換重定向到while循環:

你寫

while read line; do echo $line; done <(cat foo) 

你需要

while read line; do echo $line; done < <(cat foo) 
# ...................................^ 

治療過程中置換像一個文件名。

+0

是的,確切地說。我在你的帖子前一分鐘就知道了,並回答了我自己:)但我會刪除我的答案並接受你的答案。謝謝! –

+0

太棒了!因此'貓<(貓富)'也行! – olibre

2

我可以建議像這樣唯一的解決方法:

theproc() { for((i=0;i<5;++i)) do echo $i; } 

while read line ; do echo $line ; done <<<"$(theproc)" 
+0

不,對不起,這根本不是。我甚至不確定「eval $(貓)」應該做什麼。它會阻止並等待輸入。 –

+0

哦,<(foo)是進程替換。它將創建臨時的命名管道,執行foo過程,將其stdout重定向到命名管道,然後在前將它的stdin重定向到命名管道。有關詳細信息,請參閱bash和zsh的手冊頁。 –

+0

是的,我絕對誤解了你,但是因爲我已經更新了答案:) –

4

bash/zsh用名稱爲/dev/fd/n的管道(種類文件)替換<(cat foo),其中n是文件描述符(編號)。

您可以使用命令echo <(cat foo)檢查管道名稱。

如您所知,bash/zsh也在另一個進程中運行命令cat foo。第二個進程的輸出寫入到該命名管道。

而不進程替換:

while ... do ... done inputfile #error 
while ... do ... done < inputfile #correct 

相同的規則使用過程取代:

while ... do ... done <(cat foo) #error 
while ... do ... done < <(cat foo) #correct 

備選:

cat foo >3 & while read line; do echo $line; done <3; 
+0

有趣!你有沒有這方面的資料,或者你知道爲什麼不支持這個的原因?我沒有在手冊中找到這個。你的解決方法將在子shell中運行while循環,這會在我的真實腳本中導致問題。任何想法如何改變,以便while循環運行在主外殼? –