Bash

將標準輸出發送到鏈中的多個下游程序

  • February 17, 2022

我有一系列這樣執行的命令:

cmd1 < input > foo
cmd2 < foo > bar
cmd3 foo bar > output

有沒有辦法在沒有中間文件的情況下做到這foo一點bar

我也想避免跑cmd1兩次:

cmd3 <(cmd1 < input) <(cmd1 < input | cmd2) > output

所有 3 個命令都可能需要數小時才能執行,文件大小在 1GB 到 100GB 範圍內(生物資訊學)。

這是一個人為但可執行的範例:

function cmd1 { sed -r 's/[246]/x/g'; }
function cmd2 { sed -r 's/[135]/-/g'; }
function cmd3 { paste $1 $2; }
seq 10 > input
cmd3 <(cmd1 < input) <(cmd1 < input | cmd2)  # cmd1 runs twice

輸出

1       -
x       x
3       -
x       x
5       -
x       x
7       7
8       8
9       9
10      -0

不確定這是否有幫助,但我希望數據像這樣流動:

input --> cmd1 ---> cmd2  -->|
               |            |--> cmd3  --> output
               ------------>|

https://unix.stackexchange.com/a/43536接近,但不完全。

這樣的事情,可能嗎?

rm -f fifo
mkfifo fifo

cmd1 <input | tee fifo | cmd2 | cmd3 fifo /dev/stdin >output

這將創建一個名為fifo. 第一個命令使用 . 寫入命名管道和第二個命令的標準輸入tee。第三個命令從命名管道和標準輸入中讀取。

cmd3沒有任何中間數據儲存在磁碟上,但是如果在管道緩衝區已滿之前沒有從命名管道中消耗,或者如果cmd2與消耗的數據量相比產生的數據非常少,則管道可能會死鎖(而且,至關重要的是,在該管道的緩衝區已滿之前沒有產生足夠的cmd3消耗)。fifo您可以通過pv使用諸如緩衝來自命名管道的數據之類的東西來解決這個問題,例如 with cmd3 <( pv --quiet <fifo ) /dev/stdin,或在 writer 站點 with tee >( pv --quiet >fifo )(或其某些變體)。

引用自:https://unix.stackexchange.com/questions/691000