ボトムレスティー?

ボトムレスティー?

ターミナルで遊んでいて、次のことを実行しました。

printf 'some string\n' | {
    tee /dev/fd/3 | {
        : && sed 's/some/string/'
    }
} 3>&0

次のような内容の画面が表示された時、私は本当に驚きました。

string string
string string
string string
...

かなり長く続きました。少し短くして、わかりやすくするために、次のようにしてみましょう。

echo | tee /dev/fd/0 | sed =

私の場合、出力は次のようになります:

<num>
#blank
<num+1>
#blank
...

CTRLなどなど。私が試した数回のうち、 +に到達できた時点でC200k 行目以上でした。これを、、、で試しましたがbash、すべて同じ結果になりました。dashshzsh

そこで何が起こっているのでしょうか? ファイル記述子は、|pipe私が別々のプロセスだと思っていたプロセス間でどのように渡されるのでしょうか? これは信頼できる動作ですか、または予期される動作ですか? この効果を生成する他の方法はありますか?

参考のために:

echo '#blank' | {
    uname -r
    readlink -f /dev/fd/0
    tee /dev/fd/0
} | sed '=;5q'

出力

1
3.14.6-1-ARCH
2
/proc/24925/fd/pipe:[5851017]
3
#blank
4
#blank
5
#blank

答え1

/dev/fd/0は現在のプロセスの標準入力です。tee入力を指定されたファイルと stdout の両方に書き込みます。 はtee(空白の) 行を読み取って、その行を stdout ( sed) と自身の入力の両方に書き込みます。この場合、書き込んだ行を読み取り、それを stdout と自身の入力に書き込み、などして、(空の) 行の無限ループを作成します*。コマンドは、sed行番号を印刷してから行を印刷するだけです。

echo --> tee --> sed
      ^---+

* 単純な 以外の入力が指定された場合echo、このコマンドは入力をループして何度も繰り返します。

注意: OSX (BSD) では への書き込みが許可されていない/dev/fd/0ため、これを行うことはできません。

関連情報