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"

但这不起作用,因为分配是在子 shell 中执行的。

我可以重定向磁盘上的输出文件:

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)"

但我也想避免创建临时文件。

我也尝试过使用readand进行各种操作coproc,但问题似乎总是在于readorvar=$()会阻塞。

有没有办法让 bash 异步捕获多个命令的输出而不创建任何临时文件?

答案1

您正在寻找parset(GNU Parallel 的一部分)。

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

parset构建于 GNU Parallel 之上,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

将运行三个命令。我们不知道哪个会是掉队者。

你(粗略地)说过你希望这一切发生。

one    &
two    &
three  &
wait

问题是,这会产生三行输出,所有输出都以随机顺序混杂在一起。

这听起来不像是一个难题。只需标记每个输出行即可。

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

现在您需要解析三行输出,它们可以方便地按正确的顺序排列。根据需要将它们分配给变量。

相关内容