我如何在 Zsh 中使用浮点数 "delay"?

How can I "delay" in Zsh with a float-point number?

在 Zsh 中有一个 wait(用于进程或作业)命令、一个 while(秒数 == 延迟)命令和一个 sched(如果 shell 仍然是 运行ning) 命令,但没有 "delay" 命令。如果有的话,我担心这将仅限于整秒延迟。我需要一个 "delay" 语句,它基本上可以导致 procedure/task 在固定点数中指定的时间或直到某个时钟时间几乎不做任何事情。

大多数脚本会使用"sleep",但我希望有延迟定时器运行而不必打开IO;我正在寻求几乎任何事情都可以在 Zsh 中完成的理想。

有谁知道如何让一个函数(或者 builtin/module)以秒为单位执行浮点空闲延迟?

我会争辩说你做出了错误的假设。 zsh 是一个 shell,因此它的目的是成为一个 shell。成为 shell 的重要一点是成为 POSIX 兼容 shell。此外,由于 zsh 完全向后兼容 bash,而 bash 又完全向后兼容应该是 POISX shell.

的 bourne shell

这意味着 zsh 必须能够访问 sleep,因为 sleep is required for a POSIX shell

这就是我们对 POSIX 兼容性参数的看法。现在进行实际使用论证。大多数系统将使用 GNU coreutils sleep 来实现允许浮点参数的 sleep。因此以下是 POSIX 可移植的:

if ! sleep 0.03; then
    sleep 1
fi

并且在大多数情况下应该作为细粒度延迟工作,同时在极少数情况下仍然不会中断 OS 不使用 GNU coreutils。据我所知,这些罕见的情况只是 AIX 和 HP-UX 系统。

似乎只要 I/O 仅限于内置函数,I/O 就不会产生明显的滞后并且不依赖于 Zsh 之外的任何东西。通过 grochmal 的有用输入和大量实验,我为 read 内置命令和 : (null) 内置命令提出了一个简单的循环文件描述符:

: $(read -u 1 -t 10)

读命令的标准out作为:(null)的参数连接到zsh进行扩展,因此保证接收不到输入。知道它永远不会接收输入,我们让 read 命令用 -u 1 收听标准输出。 Zsh read 的超时选项接受浮点数;它在任何运行 Zsh 的系统上应该是一致的。最后,即使 shell 选项 ERREXIT 处于 read 超时失败状态也不应该成为问题,因为 read 实际上是 运行 在子 shell,无论如何都注定要结束,而且 : 总是 returns 正确。如果启用了 ERRRETURN 选项,我还不知道该行为,但修复方法是将 ||: 添加到 read 命令的末尾。

现在可以创建一个函数或匿名函数的别名来解释任何方式的参数或输入,以可靠地创建以秒为单位的浮点数延迟:

# function sleep {    -- optional switch-out for the system command
#                        after POSIX & GNU compatibility verified.
function delay {
   emulate -LR zsh -o extendedglob -o nullglob
   local Delay=1.
   if [[  == (#b)([[:digit:]](#c1,).(#c0,1)[[:digit:]](#c0,))(s|m|h|d|w|) ]]
   then
      if [[ $match[2] == (s|) ]] Delay=$match[1]
      if [[ $match[2] == (m) ]] Delay=$[ $match[1] * 60. ** 1 ]
      if [[ $match[2] == (h) ]] Delay=$[ $match[1] * 60. ** 2 ]
      if [[ $match[2] == (d) ]] Delay=$[ ($match[1] * 60. ** 2) * 24 ]
      if [[ $match[2] == (w) ]] Delay=$[ (($match[1] * 60. ** 2) * 24) * 7 ]
      : $(read -u 1 -t $Delay)
   else
      print -u 2 "Invalid delay time: "
      return 1
   fi
}