Shell
為不同的命令重用管道數據
我想為不同的應用程序使用相同的管道,例如:
cat my_file | { cmd1 cmd2 cmd3 }
Cmd1 應該消耗部分輸入。Cmd2 應該消耗另一部分,依此類推。
但是,每個 cmd 都會吃掉更多的輸入,然後讀取它確實需要適當的緩衝。
例如:
yes | nl | { head -n 10 > /dev/null cat } | head -n 10
從第 912 行而不是第 11 行輸出。
Tee 不是一個好的選擇,因為每個命令都應該消耗部分標準輸入。
有沒有一種簡單的方法可以讓這個工作?
您可以使用
tee
複制命令來通過許多命令處理整個流:( ( seq 1 10 | tee /dev/fd/5 | sed s/^/line..\ / >&4 ) 5>&1 | wc -l ) 4>&1 line.. 1 line.. 2 line.. 3 line.. 4 line.. 5 line.. 6 line.. 7 line.. 8 line.. 9 line.. 10 10
或使用 bash 逐行分割:
while read line ;do echo cmd1 $line read line && echo cmd2 $line read line && echo cmd3 $line done < <(seq 1 10) cmd1 1 cmd2 2 cmd3 3 cmd1 4 cmd2 5 cmd3 6 cmd1 7 cmd2 8 cmd3 9 cmd1 10
最後有一種執行方式
cmd1
,cmd2
並且cmd3
只有一次將 1/3 的流作為STDIN:( ( ( seq 1 10 | tee /dev/fd/5 /dev/fd/6 | sed -ne '1{:a;p;N;N;N;s/^.*\n//;ta;}' | cmd1 >&4 ) 5>&1 | sed -ne '2{:a;p;N;N;N;s/^.*\n//;ta;}' | cmd2 >&4 ) 6>&1 | sed -ne '3{:a;p;N;N;N;s/^.*\n//;ta;}' | cmd3 >&4 ) 4>&1 command_1: 1 command_1: 4 command_1: 7 command_1: 10 Command-2: 2 Command-2: 5 Command-2: 8 command 3: 3 command 3: 6 command 3: 9
為了嘗試這個,你可以使用:
alias cmd1='sed -e "s/^/command_1: /"' \ cmd2='sed -e "s/^/Command_2: /"' \ cmd3='sed -e "s/^/Command_3: /"'
如果在同一腳本上使用不同程序的一個流,您可以執行以下操作:
( for ((i=(RANDOM&7);i--;));do read line; echo CMD1 $line done for ((i=RANDOM&7;i--;));do read line echo CMD2 $line done while read line ;do echo CMD3 $line done ) CMD1 1 CMD1 2 CMD1 3 CMD2 4 CMD2 5 CMD2 6 CMD2 7 CMD2 8 CMD2 9 CMD3 10
為此,您可能必須將分離的腳本轉換為bash 函式才能建構一個整體腳本。
另一種方法可能是確保每個腳本不會向STDOUT輸出任何內容,而不是在每個腳本的末尾添加 a
cat
以便能夠連結它們:#!/bin/sh for ((i=1;1<n;i++));do read line pRoCeSS the $line echo >output_log done cat
最終命令可能如下所示:
seq 1 10 | cmd1 | cmd2 | cmd2