1 つのプログラムの出力を他の 2 つのプログラムにパイプする方法はありますか?

1 つのプログラムの出力を他の 2 つのプログラムにパイプする方法はありますか?

馬鹿げた質問で申し訳ありませんが、私は次のようなことを 1 行で実現しようとしています。

$ prog1 | prog2
$ prog1 | prog3

つまり、基本的には prog1 を実行し、その出力を prog2 と prog3 に別々にパイプします (チェーン パイプではありません)。最初は tee を使用しようとしましたが、出力がファイルにダンプされるため、適切ではないように思われました (これは私が望んでいることではありません)。

$ prog1 | tee prog2 | prog3 # doesn't work - creates file "prog2"

ある時点で、これを拡張して出力を 2 つ以上のプログラムにパイプすることを検討したいと思うかもしれませんが、今のところはシンプルに始めています。

$ prog1 | prog2
$ prog1 | prog3
$ prog1 | prog4
...

答え1

プロセスの置換。

... | tee >(prog2) | ...

答え2

Ignacio の回答と同様に、 を使用して一時的な名前付きパイプを使用できますmkfifo(1)

mkfifo /tmp/teedoff.$$; cmd | tee /tmp/teedoff.$$ | prog2 & sleep 1; prog3 < /tmp/teedoff.$$; rm /tmp/teedoff.$$

少し冗長ですが、 のようなプロセス置換のないシステムでも機能しますdash。 はsleep 1競合状態を処理するためのものです。

答え3

ちょっとしたユーティリティがあるpteeこれは機能します:

prog1 | ptee 2 3 4 2> >(prog2) 3> >(prog3) 4> >(prog4)

ファイルに書き込む代わりに、pteeコマンドラインで指定されたすべての fd に書き込みます。

pteeの一部であるパイプエクセク

答え4

bashisms や特別なファイルなどは必要ありません。少なくとも Linux では、必要ありません。

% { prog1 | tee /dev/fd/3 | prog2 >&2 ; } 3>&1 | prog3 

{ { printf %s\\t%s\\t%s\\n \
    "this uneven argument list" \
    "will wrap around" to \
    "different combinations" \
    "for each line." "Ill pick out" \
    "a few words" "and grep for them from" \
    "the same stream." | 
 tee /dev/fd/3 /dev/fd/4 | 
 grep combination >&2 ; } 3>&1 |
 grep pick >&2 ; } 4>&1 | 
 grep line

different combinations  for each *line.*  Ill pick out
different combinations  for each line.  Ill *pick* out
different *combinations*  for each line.  Ill pick out

強調表示された結果に星印を付けたのは、これらが同じストリームからの 3 つの結果であるだけでなく、別々のプロセス マッチgrepの結果でもあることを示すためです。grep

関連情報