bash - ディスクに書き込むことなく複数のバックグラウンドコマンドの出力をキャプチャできますか?

bash - ディスクに書き込むことなく複数のバックグラウンドコマンドの出力をキャプチャできますか?

並列化する複数のパイプラインを含むスクリプトがあります。現在は次のとおりです。

result1=$(pipeline | number | one)
result2=$(pipeline | number | two)
result3=$(pipeline | number | three)

printf 'Result 1: %s\n' "$result1"
printf 'Result 2: %s\n' "$result2"
printf 'Result 3: %s\n' "$result3"

私はこれをしたい:

result1=$(pipeline | number | one) &
result2=$(pipeline | number | two) &
result3=$(pipeline | number | three) &

printf 'Result 1: %s\n' "$result1"
printf 'Result 2: %s\n' "$result2"
printf 'Result 3: %s\n' "$result3"

ただし、割り当てはサブシェルで行われるため、これは機能しません。

ディスクの出力ファイルをリダイレクトできます。

pipeline | number | one > result1 &
pipeline | number | two > result2 &
pipeline | number | three > result3 &

wait

printf 'Result 1: %s\n' "$(<result1)"
printf 'Result 2: %s\n' "$(<result2)"
printf 'Result 3: %s\n' "$(<result3)"

しかし、一時ファイルを作成することも避けたいと思います。

readまた、さまざまなタスクにおよびを使用してみましたが、coproc問題は常に彼readまたはvar=$()ブロックのようです。

一時ファイルを生成せずにbashに複数のコマンドの出力を非同期的にキャプチャさせる方法はありますか?

答え1

parsetあなたは(GNU Parallelの一部)を探しています。

parset result1,result2,result3 'pipeline | number | {}' ::: one two three

parset長年にわたって現場でテストされたGNU Parallelに基づいて構築されました。その結果、出力に\ n、空白、TAB、*などが含まれていると(時々発生する)不快な予期しない競合状態に直面する可能性が低くなり、問題が発生する可能性も減ります。

例1:

. env_parallel.bash
env_parallel --session
pipeline() { seq 100; }
number() { perl -pe 's/^/Foo: /'; }
one() { grep 1; }
two() { grep 2; }
three() { grep 3; }
env_parset result1,result2,result3 'pipeline | number | {}' ::: one two three
env_parallel --end-session
echo "$result3"

例2:

. env_parallel.bash
pipeline() { seq 100; }
number() { perl -pe 's/^/Foo: /'; }
one() { grep 1; }
two() { grep 2; }
three() { grep 3; }
export -f pipeline number one two three
parset result1,result2,result3 'pipeline | number | {}' ::: one two three
echo "$result3"

(GNUパラレルする一時ファイルを作成しても予期しない競合が発生しても、ファイルをクリーンアップするために最善を尽くします。

答え2

3 つのコマンドが実行されます。私たちはどちらが落ち着くのかわかりません。

あなたは(おおよそ)これが起こりたいと言いました。

one    &
two    &
three  &
wait

問題は、これが3行の出力を生成し、すべてがランダムな順序で混在していることです。

これは難しい問題のように聞こえません。各出力ラインを表示するだけです。

( one   | sed -l 's/^/1 /' &
  two   | sed -l 's/^/2 /' &
  three | sed -l 's/^/3 /' &
) |
  sort -nk1 --stable |
  sed 's/^[123] //'

これで、正しい順序で便利に配置できる3行の出力を解析する必要があります。必要に応じて変数に割り当てます。

関連情報