ブライアンの答えにより、この問題に非常に興味を持ち、競合状態のないこのソリューションにつながりました。
coproc cat;
times >&${COPROC[1]};
{
exec {COPROC[1]}>&-;
mapfile -t times_a;
} <&${COPROC[0]};
これは、ブライアンのソリューションと基本的な構造が非常に似ていますが、タイミングの問題が原因でおかしなビジネスが発生しないようにするための重要な違いがいくつかあります。mapfile
ブライアンが述べたように、コプロセスのファイル記述子が完全に閉じられてクリーンアップされる前にbash インタープリターがコマンドの実行を開始するため、彼のソリューションは通常機能しmapfile
ます。
基本的に、コプロセスのstdout
ファイル記述子は、コプロセスのファイル記述子を閉じた直後に閉じられstdin
ます。コプロセスを保存する方法が必要stdout
です。
pipe の man ページには、次のものがあります。
パイプの読み取り側を参照するすべてのファイル記述子が閉じられている場合、write(2) により、呼び出しプロセスに対して SIGPIPE シグナルが生成されます。
したがって、少なくとも 1 つのファイル記述子をコプロセスに保持する必要がありますstdout
。これはRedirectionsで簡単に実現できます。exec 3<&${COPROC[0]}-
コプロセスのstdout
ファイル記述子を新しく作成されたfd 3
1に移動するようなことができます。コプロセスが終了すると、そのコプロセスのファイル記述子がまだあり、stdout
そこから読み取ることができます。
これで、次のことができます。
のみを行うコプロセスを作成しますcat
。
coproc cat;
をコプロセスにリダイレクトしtimes
ます。stdout
stdin
times >&${COPROC[1]};
コプロセスのstdout
ファイル記述子の一時コピーを取得します。
コプロセスのstdin
ファイル記述子を閉じます。(Bash-4.3 より前のバージョンを使用している場合は、eval
Brian が使用したトリックを使用できます。)
exec 3<&${COPROC[0]} {COPROC[1]}>&-;
一時ファイル記述子から変数に読み込みます。
mapfile -tu 3 times_a;
一時ファイル記述子を閉じます (必須ではありませんが、良い方法です)。
exec 3<&-;
これで完了です。ただし、物事をよりきちんとするために再構築する機会はまだいくつかあります。リダイレクト構文の性質により、このコードは次のようになります。
coproc cat;
times >&${COPROC[1]};
exec 3<&${COPROC[0]} {COPROC[1]}>&-;
mapfile -tu 3 times_a;
exec 3<&-;
次のコードと同じように動作します。
coproc cat;
times >&${COPROC[1]};
{
exec {COPROC[1]}>&-;
mapfile -tu 3 times_a;
} 3<&${COPROC[0]};
ここから、一時ファイル記述子を完全に削除して、ソリューションに導きます。
バッシュ 4.3+:
coproc cat; times >&${COPROC[1]}; { exec {COPROC[1]}>&-; mapfile -t times_a; } <&${COPROC[0]}
バッシュ 4.0+:
coproc cat; times >&${COPROC[1]}; { eval "exec ${COPROC[1]}>&-"; mapfile -t times_a; } <&${COPROC[0]}
1ここで元のファイル記述子を閉じる必要はありません。標準入力記述子が閉じられると元のファイル記述子が閉じられるため、複製するだけでかまいません。