【问题标题】:How can I set a variable to the output of an infinite loop in Posix shell script?如何在 Posix shell 脚本中将变量设置为无限循环的输出?
【发布时间】:2021-09-30 03:42:28
【问题描述】:

您可以像在 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

无论如何我可以分叉这个循环,让它永远运行,并且只要它被引用就得到最新版本的变量?我尝试了以下代码,但没有输出。

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

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

【问题讨论】:

  • 这个问题与无限循环无关。它与通过后台作业更新变量有关。 (为什么没有设置变量的问题得出的结论也有点可疑。)
  • 变量不是队列。您定义一个字符串,然后将该字符串作为值分配给名称。
  • 或者您是否真的想要一个其值每秒递增一次的变量,例如 bash 中的 SECONDS
  • @chepner 差不多。我想要一个每秒更改一次(或其他时间单位)的变量,但我有一个通用用例,因此该变量需要可更改为任何字符串。真的,我会调用另一个函数并将其输出作为新变量。
  • 这就是你必须做的;你不能在 POSIX shell 中实现你自己的自我更新变量。

标签: loops sh posix infinite-loop


【解决方案1】:

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

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

命名管道实际上就像一个文件,但它具有固定的大小。如果文件已满,则写入器将阻塞,直到通过读取它来腾出空间。同样,如果管道为空,读取器将阻塞,直到有人写入为止。

【讨论】:

  • 当我退出程序时,文件“p”仍然存在。我可以让它在程序完成后消失吗,特别是如果我按 Ctrl + C,因为我正在处理无限循环?
  • trap 'rm -f p' EXIT 放在脚本的开头。
  • 我还有一个问题。运行 cat p 时,cat 命令永远不会结束。我想抓取当前管道中的内容,然后停止阅读一段时间,但我希望管道能够更新,直到我下次阅读。从您的描述看来,除非正在主动读取该变量,否则该变量不会被更新,我认为这不是我需要的。
  • @Socowi trap 命令不会删除文件。我必须手动运行 rm -f p。
  • cannot reproduce你的问题。对我来说,每次我杀死脚本时都会删除p。可能是您在交互式外壳中而不是在脚本中吗?在这种情况下,您预计 p 何时会被删除?
【解决方案2】:

我希望这里的输出为“3”,如果我在两秒后回显“$var”,则输出“5”。

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

当然,您可以将值保存在变量中 (var=$(&lt; 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 仅用于在脚本完成后结束循环并删除临时文件。

【讨论】:

  • 不幸的是,我不能在 POSIX shell 中做我想做的事,所以我将我的代码迁移到这样的临时文件中,它现在可以工作了。我会接受的。
猜你喜欢
  • 2021-08-16
  • 1970-01-01
  • 2020-12-05
  • 1970-01-01
  • 2013-09-04
  • 2017-09-24
  • 1970-01-01
  • 2011-07-23
  • 1970-01-01
相关资源
最近更新 更多