如何在 Posix shell 脚本中将变量设置为无限循环的输出?

How can I set a variable to the output of an infinite loop in Posix shell script?

您可以像在 Bash、sh 等中那样将变量设置为子 shell 的输出

$ var=$(echo "2")

$ echo $var
2

您还可以将变量设置为循环完成后的输出。

$ i=0
$ var=$(while [ $i -ne 4 ]; do echo "$i"; i=$((i+1)); done)
$ echo "$var"
0
1
2
3

我是否可以分叉此循环,永远保持 运行ning,并在引用变量时获取最新版本的变量?我尝试了以下代码,但没有输出。

$ i=0
$ var=$(while true; do echo "$i"; i=$((i+1)); sleep 1; done) &
$ sleep 2
$ echo "$var"

我认为变量从未设置,因为循环从未完成。我希望这里的输出为“3”,如果我在 echo "$var" 两秒后输出“5”。正如@user2864740 所述,该问题与在后台分叉的进程有关。这里有解决方案吗,如果我希望我的其余代码为 运行 而无限循环为 运行ning?

你不能按照你的要求去做。但是,您可以使用命名管道代替变量。一个进程可以写入管道,另一个进程可以从中读取。

mkfifo p

i=0
while :; do
  echo "$i"
  i=$((i+1))
  sleep 2
done > p &

while IFS= read -r num; do
  echo "$num"
  sleep 1
done < p

命名管道实际上就像一个文件,但具有固定大小。如果文件已满,编写器将阻塞,直到 space 通过读取文件完成。同样,如果管道为空,reader 将阻塞,直到有人写入它。

I would like for the output to be "3" here, and if I echo "$var" two seconds later, the output "5".

您不能从(子)进程内部自动分配变量。但是您可以使用每次迭代都会覆盖的临时文件访问循环中的最新值。

当然您可以将值保存在变量中 (var=$(< file)) 或直接访问文件 (cat file)。

trap 'kill $(jobs -p); rm -f loopoutput' EXIT

i=0
while true; do echo "$i" > loopoutput; i=$((i+1)); sleep 1; done &
sleep 4
cat loopoutput
sleep 2
cat loopoutput

打印

3
5

trap 仅用于在脚本完成后结束循环并删除临时文件。