Date命令作为bash脚本中的变量.需要每次调用,而不是在变量声明期间调用



我有一个bash脚本,在某些地方我使用echo将一些消息放入日志文件中。我遇到的问题与DATE变量有关,该变量在整个脚本执行过程中都是静态的。

我有下面这个基本脚本来说明这个问题:

#!/bin/bash
DATE=`date +"%Y-%m-%dT%H:%M:%S%:z"`
echo "script started at $DATE"
echo "doing something"
sleep 2
echo "script finished at $DATE"

如果我执行这个脚本,$DATE变量的输出在两行中是相同的。是否有一些bash魔法可以很好地解决这个问题,而不必在每行中将$DATE替换为命令本身?

Thanks in advance

较新的bash/printf内置版本支持生成日期时间戳,而不需要生成调用date的子进程:

$ builtin printf --help
...snip...
Options:
-v var    assign the output to shell variable VAR rather than
display it on the standard output
...snip...
In addition to the standard format specifications described in printf(1),
printf interprets:
%b        expand backslash escape sequences in the corresponding argument
%q        quote the argument in a way that can be reused as shell input
%(fmt)T   output the date-time string resulting from using FMT as a format
string for strftime(3)
... snip ...

不生成子进程调用date,例如:

logdt=`date +"%Y-%m-%dT%H:%M:%S:%z"`

同样可以通过printf -v通过在%(...)T中包装所需的格式来完成,例如:

printf -v logdt '%(%Y-%m-%dT%H:%M:%S:%z)T'

注意:假设%:z应为:%z

假设你将用日期时间戳标记很多行,那么从消除子进程date调用中节省的费用可能是巨大的。

运行1000个日期时间戳世代的测试:

$ time for ((i=1;i<=1000;i++)); do { printf -v logdt '%(...)T' | logdate=$(date ...) }; done

printf -v logdt '%(...)T'的时序:

real    0m0.182s              # ~130 times faster than $(date ...)
user    0m0.171s
sys     0m0.000s

logdt=$(date ...)的时序:

real    0m24.443s             # ~130 times slower than printf -v 
user    0m5.533s
sys     0m16.724s

对于bash 4.3+版本,您可以使用内置的printf来格式化日期时间。下面的-1是一个魔法值,它的意思是"现在"。

#!/bin/bash
datefmt='%Y-%m-%dT%H:%M:%S%z'
printf "script started at %($datefmt)Tn" -1
echo "doing something"
sleep 2
printf "script finished at %($datefmt)Tn" -1

bash不识别%:z

这可以帮助你:

#!/bin/bash
echo "script started at $(date +'%Y-%m-%dT%H:%M:%S%:z')"
echo "doing something"
sleep 2
echo "script finished at $(date +'%Y-%m-%dT%H:%M:%S%:z')"

如果调用完整的命令对您来说显得笨拙,您可能需要创建一个别名。

最新更新