2013-04-17 26 views
4

根據維基百科的說法,「過程替換也可用於捕獲通常會轉到文件並將其重定向到進程輸入的輸出。」(http://en.wikipedia.org/wiki/Process_substitution)。因此,用我自己的話來說,這意味着通過進程替換,我可以接收命令A的輸出並將其用作命令B的輸入。換句話說,它就像一個管道(這是否正確? )。bash前進過程替換背後發生了什麼?

因此,如果這是真的,如果我這樣做:

echo "test" >(wc) 

話,我應該會得到如下:

1 1 5 

,因爲我上面的命令的理解是類似於以下:

$echo "test" > tmp 
$wc tmp 
1 1 5 tmp 

除了我不使用進程替換的tmp文件。

而是我得到以下輸出:

test /dev/fd/63 

這顯然表明不知我的心智模式是不正確。我錯在哪裏?

我明白<(命令)。例如

$diff <(head file1) <(head file2) 

完全有道理。但不是>(命令)。

回答

3

Process Substitution

進程列表與其輸入或連接到一個 FIFO輸出或的/ dev/FD一些文件中運行。 作爲擴展的結果,此文件的名稱作爲參數傳遞給當前命令。如果使用>(列表)表單,則寫入文件將爲列表提供輸入。

echo "test" >(wc)會發生什麼情況?

打開文件/dev/fd/63以連接echo testwcwc開始於它的輸入連接到/dev/fd/63。然後將該文件的名稱(/dev/fd/63)作爲參數傳遞給當前命令(echo "test"),結果爲echo "test" /dev/fd/63。這就是爲什麼你看到

test /dev/fd/63 

作爲輸出。 wc等待輸入,但由於echo未寫入/dev/fd/63,因此計數將爲0

如果你想要這個工作,你必須創建一個腳本,它接受一個參數與回聲第一N-1爭論到最後

#! /bin/bash 
echo "${@:1:$(($# - 1))}" >${@: -1} 

當調用此

bash script.sh test >(wc) 

你會看到預期的輸出

1 1 5 
+3

或者,更簡單地,可使用:'回波測試>>(WC)',它重定向的「echo'輸出由所述進程替換指定的文件。 –

+0

@JonathanLeffler哇!我真的很感動。所以,這個名字不會作爲參數傳遞,而是從字面上追加到命令字符串中。謝謝。 –

+0

查看在[shell擴展]在'bash'手冊的討論(http://www.gnu.org/software/bash/manual/bash.html#Shell-Expansions)並按照其描述了特定的擴展部分,並且然後在所有擴展之後發生[重定向](http://www.gnu.org/software/bash/manual/bash.html#Redirections)。 –

2

你的心智模式是錯誤的是你錯過了一個重要的細節:流程替代不是重定向。

當您執行諸如「echo test> tmp」之類的重定向時,執行的是「echo test」,stdout(由「>」表示)指向名爲「tmp」的文件。當執行替換,諸如「回波試驗>(WC)」中,「WC」被執行,並且「>(WC)」是由一個文件的名稱(或者可能是一個神奇設備的名稱)代替可以讀取或寫入。

,作爲您鏈接到維基百科頁面引用:「引擎蓋下,進程替換的工作方式是創建一個命名管道,然後在命令行上替代它的名字。」

如果您在上面的「差異」的例子仔細觀察,你會發現有作爲,它的工作方式相同。畢竟,「diff」的參數是什麼,而命令行上的文件名是什麼?

+0

所以這意味着執行的優先級是1)wc裏面>()和2)echo命令? – Alby

+0

如果我正確理解了你,使用其他示例'$ tee>(wc -l>&2) bigfile.gz',這裏bigfile被讀取並且成爲wc -l在>()內的輸入,並且該輸出作爲輸入到tee? – Alby

+1

示例'$ tee>(wc -l>&2) bigfile.gz'相當於'$ cat bigfile | tee>(wc -l>&2)| gzip> bigfile.gz'。 tee命令在stdin上獲取bigfile,stdout是一個用於gzip的管道,而tee的**命令行參數**是一個代表wc進程的stdin的文件名。 –

相關問題