Ant*_*ber 4 bash timestamps printf
壳牌:猛击。
目标:获取自某个固定时间点以来的时间 t(以毫秒为单位),适用于使用 printf 为内容添加时间戳。
条件:解决方案必须通过多合一文本行测试。
附加:解决方案应该是原子的(是的,对!..),轻量级,将量化和舍入问题保持在最低限度,等等..
t=$[$(date +%s%N)/1000000]
<--- 我的解决方案,在这种情况下,固定点是 1970 年 1 月 1 日。但由于两次约会电话,从根本上来说很糟糕。
printf "t=%d\n" $[$(date +%s%N)/1000000]
<--- 在这里,使用 printf。
t=$(date +%s)$[10#$(date +%N)/1000000]
<--- 可怕的例子。甚至似乎需要取消填充,然后重新填充前导零。
printf "t=%d%03d\n" $(date +%s) $[10#$(date +%N)/1000000]
<--- 在这里,使用 printf。
有什么更好的(明智的)建议吗?
编辑(附加):
t=$(date +%s%N)
然后printf "%s\n" ${t::13}
<--- 我猜,但不是一行。
正如@Isaac指出,与date
实现,支持%N
像GNU的或AST开放的,你可以使用%s%3N
限制的精度,但除了在ksh93
这里date
可以被制成AST-开放的的内置版本date
,该date
命令不被内置。启动需要几百甚至几千微秒,打印日期和返回需要更多时间。
bash
确实复制了ksh93
printf '%(...)T'
格式的子集,但不是%N
部分。
在这里,您似乎需要使用更高级的 shell,例如ksh93
或zsh
。
这些外壳程序可以使它们的$SECONDS
变量记录自外壳程序启动以来的时间(并且您也可以重置为任何值)浮点数:
$ typeset -F SECONDS=0; date +%s%3N; echo $SECONDS
1506318780647
0.0017870000
Run Code Online (Sandbox Code Playgroud)
date
在这里运行 GNU 最多需要 1787 微秒。
您可以使用$((SECONDS*1000))
来获取毫秒数,因为两个 shell 都支持浮点运算(注意ksh93
尊重语言环境的小数点)。
对于作为浮点数的纪元时间,zsh
有$EPOCHREALTIME
:
$ zmodload zsh/datetime
$ echo $EPOCHREALTIME
1506318947.2758708000
Run Code Online (Sandbox Code Playgroud)
并且ksh93
可以使用"$(printf '%(%s.%N)T' now)"
(请注意,ksh93
的命令替换不会派生进程,也不会为内置函数使用管道,因此不像其他类似 Bourne 的 shell 那样昂贵)。
您还可以在$EPOCHREALTIME
那里定义变量:
$ EPOCHREALTIME.get() { .sh.value=$(printf "%(%s.%6N)T");
$ echo "$EPOCHREALTIME"
1506333341.962697
Run Code Online (Sandbox Code Playgroud)
对于自动时间戳,您还可以使用set -o xtrace
和 a$PS4
打印当前时间。在zsh
:
$ zsh -c 'PS4="+%D{%s.%.}> "; set -x; sleep 1; date +%s.%N'
+1506332128.753> sleep 1
+1506332129.754> date +%s.%N
1506332129.755322928
Run Code Online (Sandbox Code Playgroud)
在 ksh93 中:
$ ksh -c 'PS4="+\$(printf "%(%s.%3N)T")> "; set -x; sleep 1; date +%s.%N'
+1506332247.844> sleep 1
+1506332248.851> date +%s.%N
1506332248.853111699
Run Code Online (Sandbox Code Playgroud)
根据您的用例,您可以依靠moreutils
'sts
来标记时间戳:
$ (date +%s.%6N; date +%s.%6N) | ts %.s
1506319395.000080 1506319394.970619
1506319395.000141 1506319394.971972
Run Code Online (Sandbox Code Playgroud)
(ts
给出它date
通过管道从的输出中读取行的时间)。
或者输出行之间的时间:
$ (date +%s.%6N; date +%s.%6N) | ts -i %.s
0.000011 1506319496.806554
0.000071 1506319496.807907
Run Code Online (Sandbox Code Playgroud)
如果您想获得运行给定命令(管道)所需的时间,您还可以使用time
关键字,使用$TIMEFORMAT
in调整格式bash
:
$ TIMEFORMAT=%E; time date
Mon 25 Sep 09:51:41 BST 2017
0.002
Run Code Online (Sandbox Code Playgroud)
这些时间格式指令最初来自CSH(虽然bash
,违背zsh
或GNUtime
只支持一个小的子集)。在 (t)csh 中,您可以通过设置$time
特殊变量来计时每个命令:
$ csh -xc 'set time = (0 %E); sleep 1; sleep 2'
set time = ( 0 %E )
sleep 1
0:01.00
sleep 2
0:02.00
Run Code Online (Sandbox Code Playgroud)
(第一个数字(0
此处)表示应该对耗时超过该秒数的命令进行计时,第二个数字指定格式)。
由于 bash5+ 有一个简单的解决方案:
$ printf "%.3f\n" $EPOCHREALTIME
1566917328.786
Run Code Online (Sandbox Code Playgroud)
如果不需要点:
printf "%s\n" "$((${EPOCHREALTIME/.}/1000))"
Run Code Online (Sandbox Code Playgroud)
提供自纪元以来的毫秒数,全合一文本行,原子性(对内部 bash 变量的一次调用),轻量级,并且没有量化或舍入问题。
归档时间: |
|
查看次数: |
6516 次 |
最近记录: |