通常paste
印刷二つ隣接列の名前付き(またはそれに対応する)ファイルは次のとおりです。
paste <(printf '%s\n' a b) <(seq 2)
出力:
a 1
b 2
しかし、両方のファイルがあります /dev/stdin
。/dev/stderr
私たちが持っているとしましょう。雨部族雨箱2行を出力するプログラム標準出力そして2行標準エラー。説明のために、次の関数を使用してこれをシミュレートできます。
bb() { seq 2 | tee >(sed 's/^/e/' > /dev/stderr) ; }
今走るannotate-output
、(内部に開発スクリプトカプセル化Debian/Ubuntu/など。)動作していることを示すために:
annotate-output bash -c 'bb() { seq 2 | tee >(sed 's/^/e/' > /dev/stderr) ; }; bb'
22:06:17 I: Started bash -c bb() { seq 2 | tee >(sed s/^/e/ > /dev/stderr) ; }; bb
22:06:17 O: 1
22:06:17 E: e1
22:06:17 O: 2
22:06:17 E: e2
22:06:17 I: Finished with exitcode 0
だから動作します。フィードbb
:paste
bb | paste /dev/stdin /dev/stderr
出力:
1 e1
e2
^C
停止 -^C
押されたという意味Control-Cやめる。
|
次のいずれかに変更して;
も機能しません。
bb ; paste /dev/stdin /dev/stderr
出力:
1
2
e1
e2
^C
また、一時停止 -^C
押されたことを意味します。Control-Cやめる。
希望の出力:
1 e1
2 e2
を使用して実行できますかpaste
?そうでなければなぜならないのですか?
ベストアンサー1
/dev/stderrをパイプとして使用できないのはなぜですか?
問題はそうpaste
ではありません/dev/stdin
。それと一緒に行きます/dev/stderr
。
すべてのコマンドは、1つのオープン入力記述子(0:標準入力)と2つの出力(1:標準出力と2:標準エラー)で生成されます。通常、それぞれと/dev/stdin
名前を使用してアクセスできますが、以下を参照してください。/dev/stdout
/dev/stderr
/dev/stdin、/dev/stdout、および/dev/stderrの移植性はどのくらいですか?。 (含むpaste
)多くのコマンドもファイル名を-
STDINとして解釈します。
個別に実行すると、bb
STDOUTとSTDERRの両方がコンソールであり、通常はコマンド出力が表示されます。行は(あなたの説明のように)別の記述子を通過しますannotate-output
が、同じ位置に終わります。
1 つ目と 2 番目のコマンドを追加すると、|
パイプが生成されます。
bb | paste /dev/stdin /dev/stderr
|
の出力をbb
の入力に接続するようにシェルに指示しますpaste
。 paste
まず読んでください/dev/stdin
。これは(一部のシンボリックリンクを介して)独自の標準入力記述子(シェルが接続したばかりのもの)として解釈され、行が渡されるようにし1
ます。
ただし、シェル/パイプラインはSTDERRには影響しません。 bb
それでもe1
e2
コンソールに転送中です。同時にpaste
同じコンソールからデータを読み取ろうとすると、コンソールは停止します(何かを入力するまで)。
あなたのリンクテキストエディタを使用して/dev/stdoutを読み取れないのはなぜですか?/dev/stderr
.
2番目のパイプを作成する方法
標準出力と標準エラーを生成するコマンドがあり、paste
これら2行を互いに隣に置きたいです。これは、各列に1つずつ2つの同時パイプラインを意味します。シェルパイプは... | ...
これらのうちの1つを提供します。 2番目のパイプを直接作成し、.redirectを使用してSTDERRをそのパイプにリダイレクトする必要があります2>filename
。
mkfifo RHS
bb 2>RHS | paste /dev/stdin RHS
これがスクリプト内で使用されている場合は、FIFOを一時ディレクトリに配置し、使用後に削除することをお勧めします。