日期命令作为 bash 脚本中的变量。需要每次调用而不是在变量声明期间调用
Date command as a variable in a bash script. Needs to be invoked each time instead of during variable declaration
我有一个 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?
提前致谢
这可以帮助你:
#!/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')"
如果您觉得调用完整命令很笨拙,您可能想要创建一个别名。
使用 bash 4.3+ 版,您可以使用内置 printf
来格式化日期时间。 -1
下面是一个神奇的值,表示“现在”。
#!/bin/bash
datefmt='%Y-%m-%dT%H:%M:%S%z'
printf "script started at %($datefmt)T\n" -1
echo "doing something"
sleep 2
printf "script finished at %($datefmt)T\n" -1
bash 没认出我 %:z
。
较新版本的 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 脚本,在某些时候我使用 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?
提前致谢
这可以帮助你:
#!/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')"
如果您觉得调用完整命令很笨拙,您可能想要创建一个别名。
使用 bash 4.3+ 版,您可以使用内置 printf
来格式化日期时间。 -1
下面是一个神奇的值,表示“现在”。
#!/bin/bash
datefmt='%Y-%m-%dT%H:%M:%S%z'
printf "script started at %($datefmt)T\n" -1
echo "doing something"
sleep 2
printf "script finished at %($datefmt)T\n" -1
bash 没认出我 %:z
。
较新版本的 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