Printf 格式化 ZSH 变量而不分叉?

Printf 格式化 ZSH 变量而不分叉?

对于我的 powerlevel10k 自定义提示,我目前有此功能来显示自纪元以来的秒数,以逗号分隔。我将它显示在当前时间下,这样我总是有一个提示来大致记住当前纪元时间是什么。

function prompt_epoch() {
  MYEPOCH=$(/bin/date +%s | sed ':a;s/\B[0-9]\{3\}\>/,&/;ta')
  p10k segment -f 66 -t ${MYEPOCH}
}

我的提示看起来像这样: 提示示例截图

有人告诉我可以使用以下命令在没有分叉进程的情况下执行此操作:

$ zmodload -F zsh/datetime p:EPOCHSECONDS
$ printf "%'d" $EPOCHSECONDS
1,648,943,504

但我不确定如何在不分叉的情况下做到这一点。我知道在获取 powerlevel10k 之前zmodload在 my 中添加该行,但是我不知道如何在没有 fork 的情况下进行格式化。~/.zshrc${EPOCHSECONDS}

如果我按照我知道的方式做,这就是我会做的:

function prompt_epoch() {
  MYEPOCH=$(printf "%'d" ${EPOCHSECONDS})
  p10k segment -f 66 -t ${MYEPOCH}
}

但据我了解,每次调用提示时仍然会分叉一个进程,对吗?我是否误解了给出的建议,因为我认为我无法找到一种方法来获取最新纪元秒数而不运行某种需要分叉的进程,对吗?

答案1

printf中的实用程序都有一个允许您“打印到变量”的选项:bashzsh-v

printf -v MYEPOCH "%'d" ${EPOCHSECONDS}

上述命令的实际结果很可能取决于当前区域设置。

答案2

FWIW,你还可以这样做:

zmodload zsh/datetime
set -o histsubstpattern -o promptsubst -o extendedglob
RPS1='$EPOCHSECONDS:fs/%(#b)([^,])([^,](#c3)(|,*))/$match[1],$match[2]'

获得类似于1,648,989,768正确提示的内容,而无需分叉进程,也不依赖于语言环境来获取千位分隔符的值。

${param:fs/left/right}使用s替代品历史修改器就像在 csh 中一样,而f只要它改变了一些东西,就会重复它,实现类似于 GNUsed方法的东西。

启用该histsubstpattern选项后,left可以是一个模式,因此$param:s/left/right行为类似于 ksh93,${param/pattern/replacement}只不过我们可以将它与该f修饰符结合起来,这使得它在这里更有用。

与 ksh93 一样${param/pattern/replacement},模式前面可以有 ,%仅在主题末尾匹配。通过extendedglob,我们可以启用反向引用(#b)或使用(#c3)来匹配前面的 3 个原子,如 ERE 的{3}

请注意,除了$EPOCHSECONDS(需要加载模块zsh/datetime)之外,纪元时间也可以通过提示扩展来获取%D{%s}。为了能够对其应用修改器,您必须将其作为参数扩展的一部分进行扩展。这可以通过%参数扩展标志来完成:

set -o histsubstpattern -o promptsubst -o extendedglob
RPS1='${${(%):-"%D{%s}"}:fs/%(#b)([^,])([^,](#c3)(|,*))/$match[1],$match[2]}'

相关内容