首頁 > shell教程 閱讀:0更新時間:2020-03-28 02:19:15

Shell進程替換(把一個命令的輸出傳遞給另一個命令)

進程替換和命令替換非常相似。命令替換是把一個命令的輸出結果賦值給另一個變量,例如dir_files=`ls -l`date_time=$(date);而進程替換則是把一個命令的輸出結果傳遞給另一個(組)命令。

為了說明進程替換的必要性,我們先來看一個使用管道的例子:

echo "http://www.beylze.com/d/file/20190908/y5jvity5mfg.html | read
echo $REPLY

以上代碼輸出結果總是為空,因為 echo 命令在父 shell 中執行,而 read 命令在子 Shell 中執行,當 read 執行結束時,子 Shell 被銷毀,REPLY 變量也就消失了。管道中的命令總是在子 Shell 中執行的,任何給變量賦值的命令都會遭遇到這個問題。

使用 read 讀取數據時,如果沒有提供變量名,那么讀取到的數據將存放到環境變量 REPLY 中,這一點已在《Shell read》中講到。

幸運的是,Shell 提供了一種“特異功能”,叫做進程替換,它可以用來解決這種麻煩。

Shell 進程替換有兩種寫法,一種用來產生標準輸出,借助輸入重定向,它的輸出結果可以作為另一個命令的輸入:

<(commands)

另一種用來接受標準輸入,借助輸出重定向,它可以接收另一個命令的輸出結果:

>(commands)

commands 是一組命令列表,多個命令之間以分號;分隔。注意,<>與圓括號之間是沒有空格的。

例如,為了解決上面遇到的問題,我們可以像下面這樣使用進程替換:

read < <(echo "http://www.beylze.com/d/file/20190908/y5jvity5mfg.html)
echo $REPLY

輸出結果:
http://c.biancheng.net/shell/

整體上來看,Shell 把echo "http://www.beylze.com/d/file/20190908/y5jvity5mfg.html的輸出結果作為 read 的輸入。<()用來捕獲 echo 命令的輸出結果,<用來將該結果重定向到 read。

注意,兩個<之間是有空格的,第一個<表示輸入重定向,第二個<()連在一起表示進程替換。

本例中的 read 命令和第二個 echo 命令都在當前 Shell 進程中運行,讀取的數據也會保存到當前進程的 REPLY 變量,大家都在一個進程中,所以使用 echo 能夠成功輸出。

而在前面的例子中我們使用了管道,echo 命令在父進程中運行,read 命令在子進程中運行,讀取的數據也保存在子進程的 REPLY 變量中,echo 命令和 REPLY 變量不在一個進程中,而子進程的環境變量對父進程是不可見的,所以讀取失敗。

再來看一個進程替換用作「接受標準輸入」的例子:

echo "C語言中文網" > >(read; echo "你好,$REPLY")

運行結果:
你好,C語言中文網

因為使用了重定向,read 命令從echo "C語言中文網"的輸出結果中讀取數據。

Shell進程替換的本質

為了能夠在不同進程之間傳遞數據,實際上進程替換會跟系統中的文件關聯起來,這個文件的名字為/dev/fd/n(n 是一個整數)。該文件會作為參數傳遞給()中的命令,()中的命令對該文件是讀取還是寫入取決于進程替換格式是<還是>

  • 如果是>(),那么該文件會給()中的命令提供輸入;借助輸出重定向,要輸入的內容可以從其它命令而來。

  • 如果是<(),那么該文件會接收()中命令的輸出結果;借助輸入重定向,可以將該文件的內容作為其它命令的輸入。


使用 echo 命令可以查看進程替換對應的文件名:

[c.biancheng.net]$ echo >(true)
/dev/fd/63
[c.biancheng.net]$ echo <(true)
/dev/fd/63
[c.biancheng.net]$ echo >(true) <(true)
/dev/fd/63 /dev/fd/62

/dev/fd/目錄下有很多序號文件,進程替換一般用的是 63 號文件,該文件是系統內部文件,我們一般查看不到。

我們通過下面的語句進行實例分析:

echo "shellscript" > >(read; echo "hello, $REPLY")

第一個>表示輸出重定向,它把第一個 echo 命令的輸出結果重定向到/dev/fd/63文件中。

>()中的第一個命令是 read,它需要從標準輸入中讀取數據,此時就用/dev/fd/63作為輸入文件,把該文件的內容交給 read 命令,接著使用 echo 命令輸出 read 讀取到的內容。

可以看到,/dev/fd/63文件起到了數據中轉或者數據橋梁的作用,借助重定向,它將>()內部的命令和外部的命令聯系起來,使得數據能夠在這些命令之間流通。

beylze編程學院,一個分享編程知識和seo優化知識的網站。跟著beylze一起學習,每天都有進步。

通俗易懂,深入淺出,一篇文章只講一個知識點。

文章不深奧,不需要鉆研,在公交、在地鐵、在廁所都可以閱讀,隨時隨地漲姿勢。

文章不涉及代碼,不燒腦細胞,人人都可以學習。

當你決定關注beylze(公眾號:beylze),你已然超越了90%的其他從業者!

相關文章

優秀教程

国产亚洲欧美日韩