Zsh

在 zsh 中時間命令的輸出中顯示變數的值

  • April 7, 2022

我想為一系列輸入變數測量我的程序的執行時間(我正在使用 zsh):

for i in {1..3} ; do time sleep $i ; done

輸出是

sleep $i  0,00s user 0,00s system 0% cpu 1,003 total
sleep $i  0,00s user 0,00s system 0% cpu 2,003 total
sleep $i  0,00s user 0,00s system 0% cpu 3,002 total

但我希望它是

sleep 1  0,00s user 0,00s system 0% cpu 1,003 total
sleep 2  0,00s user 0,00s system 0% cpu 2,003 total
sleep 3  0,00s user 0,00s system 0% cpu 3,002 total

如何time列印實際命令,所有變數都替換為它們的值?


我已經嘗試在子 shell 中執行程序,它沒有按預期更改輸出:

for i in {1..3} ; do time (sleep $i) ; done

由於我的程序產生自己的輸出到 stdout 和 stderr,我看不到一種方法來簡單地預先添加所有參數(還有一些不僅僅是i),例如:

for i in {1..3} ; do echo -n "i=$i --> " ; time sleep $i ; done

發生這種情況是因為time是一個可以作用於復合命令的關鍵字。(更準確地說,它作用於管道。)您可以編寫類似

time (i=$(($(/bin/echo 1) + 1)); sleep $i)

並且 zsh 用於解析命令(包括計算$i)的時間是計時的一部分。

一種解決方案是改用time外部命令。這作用於外部命令,因此 shell 擴展不是計時的一部分。使用 GNU 時間(預設情況下不列印命令):

% for i in {1..3} ; do =time -f '%C  %Us user %Ss system %P cpu %e total' sleep $i ; done
sleep 1  0.00s user 0.00s system 0% cpu 1.00 total
sleep 2  0.00s user 0.00s system 0% cpu 2.00 total
sleep 3  0.00s user 0.00s system 0% cpu 3.00 total

另一種解決方案是自己列印命令。請注意,下面的程式碼會在命令輸出之前列印命令文本(如果有)。

% for i in {1..3} ; do echo -n "sleep $i"; (TIMEFMT=${TIMEFMT#%J}; time sleep $i); done
sleep 1  0.00s user 0.00s system 0% cpu 1.004 total
sleep 2  0.00s user 0.00s system 0% cpu 2.004 total
sleep 3  0.00s user 0.00s system 0% cpu 3.004 total

另一種解決方案是啟動命令跟踪。

% for i in {1..3} ; do (TIMEFMT=${TIMEFMT#%J}; set -x; time sleep $i); done     
+zsh:14> sleep 1
 0.00s user 0.00s system 0% cpu 1.004 total
+zsh:14> sleep 2
 0.00s user 0.00s system 0% cpu 2.004 total
+zsh:14> sleep 3
 0.00s user 0.00s system 0% cpu 3.005 total

另一種解決方案是將您想要的文本注入時間格式。

% for i in {1..3} ; do (TIMEFMT="${${:-sleep $i}//\%/%%}${TIMEFMT#%J}"; time sleep $i); done
sleep 1  0.00s user 0.00s system 0% cpu 1.004 total
sleep 2  0.00s user 0.00s system 0% cpu 2.004 total
sleep 3  0.00s user 0.00s system 0% cpu 3.004 total

另一種解決方案是盡可能建構最簡單的 shell 命令eval。由於這涉及eval,因此如果命令可能包含 shell 特殊字元,請小心。

% for i in {1..3} ; do eval "time sleep $i"; done                  
sleep 1  0.00s user 0.00s system 0% cpu 1.002 total
sleep 2  0.00s user 0.00s system 0% cpu 2.005 total
sleep 3  0.00s user 0.00s system 0% cpu 3.004 total

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