`>()`サブシェルがリダイレクトの一部である場合(例:`>>()`)標準出力が異なるのはなぜですか?

`>()`サブシェルがリダイレクトの一部である場合(例:`>>()`)標準出力が異なるのはなぜですか?

これは次の質問です。`...>>(sed's/^/stdout: /')` は印刷されません。 sed 's / ^ / stdout:/ 'が空の標準入力に印刷されるのはなぜですか?

より具体的にこれがパイプである理由は次のとおりです。

$ tee 2> >(readlink /proc/self/fd/1) < /dev/null | cat        
pipe:[17955449]

これが最終デバイスの場合はいつですか? :

$ tee >(readlink /proc/self/fd/1) < /dev/null | cat   
/dev/pts/31

私は前者の出力がコマンドを入力したシェルから自然に継承されると思いました。しかし、bashとzshの両方がリダイレクトされるように、コマンドの出力をリダイレクトするために明示的な手順を実行する必要があるようです。彼らはなぜこのようなことをするのですか?それとも別のことが起こっていますか?前者のサブシェルはtee'ing'前のプロセスで生成されますか?一方のサブシェルは子プロセスから継承され、他のサブシェルは親プロセスから継承されますか?どのように?exectee

うーん...タグ付けして確認しながら、bashどちらの場合もbashのパイプであることがわかりました...だからこれはzsh機能です。

答え1

zsh は同じコマンドに対する複数のリダイレクトをサポートします。たとえば、abc > def > ghi出力全体をabcsumdefに入れますghi。また、2つと>1つの装飾されていないリダイレクトを同時に許可します。これは、最初の例で使用したリダイレクトです。|

複数のリダイレクトの場合、プロセスはリダイレクトに置き換えられます。

tee 2> >(readlink /proc/self/fd/1) < /dev/null | cat

出力は基本コマンドと同様にパイプで接続され、プロセス交換をそのコマンドにリダイレクトする必要はありません。

tee >(readlink /proc/self/fd/1) < /dev/null | cat

いいえ。パイプラインは、リダイレクトされた分岐のすべての出力がパイプラインを通過するという点で優先順位があります。この場合、2つの分岐(メインコマンド自体とプロセス交換の出力)があり、両方が通過するため、両方ともcat標準出力をパイプとして扱います。

Bashは常に代替エントリをユーザーにパイプcatし、最初はこのような複数のリダイレクトをサポートしません。

本質的に、zshで複数のリダイレクトがあります、まだ1つしか|ありません。パイプラインはリダイレクトのすべてのブランチに分散されます。、しかしプロセス置換自体は、プロセス置換の一部ではありません。- 実際の出力リダイレクトのみ可能です>

これは、プロセス置換によって表示されるリダイレクトの属性です。リダイレクトされたプロセスオーバーライドとリダイレクトされていないプロセスオーバーライドの両方を使用でき、次のことを確認できます。

$ true >( readlink /proc/self/fd/1 ) > >( readlink /proc/self/fd/1 ) | cat
/dev/tty1
pipe:[2975]

最初(代替)はTTYを標準出力として使用し、2番目(リダイレクト)は入力をcat。これがこの設定を構築する唯一の簡単な方法です。つまり、パイプで接続されたコマンドの単一インスタンスと、その前にパイプされたコマンドとパイプされていないコマンドが混在しています。望ましくないときに間違ったトラックから出力をリダイレクトした場合は、リカバリを使用できますが、> /dev/pts/...Bashのようにデフォルトの交換リダイレクトが本当に必要な場合は、まだ幸運ではありません。

プロセスの交換自体はシェルから環境を継承し、リダイレクトはパイプの要素だけでなく入力と出力も変更します。私の考えではこれではないと思います。必要これは次のように機能しますが、一貫した規則に従います。|常に配布されますが、>パラメータは無視されます。

私の実験は実際の動作を説明していますが、ここにインラインで含めるには長すぎて扱いにくいですが、この回答の改訂履歴から。以下に、4つの状況(はい/いいえ、>および)とその動作をまとめました|


ケース分析

通常、zshは4つのケースで動作します。

  1. |、いいえ>

    abc >( def ) | ghi
    

    これは基本コマンドの出力をパイプに送り、サブシェルの出力をTTYに送り、パスをabc

  2. いいえ|>

    abc >( def )
    

    その後、すべてがTTYに送信され、パスがabc

  3. いいえ|、しかし>

    abc > >( def )
    

    これは引数を提供せず、基本コマンドの出力をサブシェルに送信し、サブシェルをTTYに送信しますabc

  4. |そして>

    abc > >( def ) | ghi
    

    これにより、基本コマンドの出力が次に送信されます。両方プロセスの置き換えとパイプだけでなく、サブシェルからパイプへの出力も提供しませんabcabc | tee >( def ) | ghi

私はケース4がケース1とは異なり、変化がパイプから離れすぎているように感じますが、それはまさにその点が好きではありません。

関連情報