Zsh

Printf 在不分叉的情況下格式化 ZSH 變數?

  • April 4, 2022

對於我的 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行,但格式化不是我知道如何在沒有叉子的情況下做的事情。~/.zshrc``${EPOCHSECONDS}

如果我按照我知道的方式做,我會這樣做:

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

但據我了解,每次呼叫提示時仍然會分叉一個程序,對嗎?我是否誤解了給出的建議,因為我認為我無法在不執行某種需要分叉的程序的情況下獲得最新的紀元秒數,對嗎?

兩者中的printf實用程序都有一個允許您“列印到變數”的選項:bash``zsh``-v

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

上述命令的實際結果很可能取決於目前的語言環境。

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}使用像 csh 中的substitute歷史修飾符f,而只要它改變了一些東西,它就會重複它,實現類似於你的 GNUsed方法的東西。

histsubstpattern啟用該選項後,left它可以是一種模式,因此$param:s/left/right其行為類似於 ksh93 ,${param/pattern/replacement}除了我們可以將它與該f修飾符結合使用,這使得它在這裡更有用。

與 ksh93’s 一樣${param/pattern/replacement},模式前面%可以匹配僅在主題的末尾。使用extendedglob,我們可以啟用反向引用(#b)或使用(#c3)來匹配前面的 3 個原子,如 ERE 的{3}

注意除了$EPOCHSECONDS(需要載入zsh/datetime模組),epoch時間也可以通過%D{%s}提示展開獲取。為了能夠對其應用修飾符,您必須將其作為參數擴展的一部分進行擴展。這可以通過%參數擴展標誌來完成:

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

引用自:https://unix.stackexchange.com/questions/697806