解析 Bash 内置时间的输出
Posted
技术标签:
【中文标题】解析 Bash 内置时间的输出【英文标题】:Parsing the output of Bash's time builtin 【发布时间】:2015-01-03 06:40:45 【问题描述】:我正在从一个 Bash 脚本运行一个 C 程序,并通过一个名为 time 的命令运行它,该命令会输出一些运行算法的时间统计信息。
如果我要执行命令
time $ALGORITHM $VALUE $FILENAME
它产生输出:
real 0m0.435s
user 0m0.430s
sys 0m0.003s
取决于算法运行的值
但是,我希望能够做的是获取 0.435 并将其分配给一个变量。 我已经读了一点 awk,足以知道如果我将上述命令输入 awk,我应该能够获取 0.435 并将其放入变量中。但是我该怎么做呢?
非常感谢
【问题讨论】:
您是否只想将0.435
存储为实线?
Struggling to parse (bash) time command 的可能重复项
【参考方案1】:
您必须小心:Bash 内置 time
和外部命令 time
,通常位于 /usr/bin/time
(键入 type -a time
以在您的系统上拥有所有可用的 time
s)。
如果你的 shell 是 Bash,当你发出
time stuff
您正在调用内置函数time
。如果没有一些小技巧,您将无法直接捕获 time
的输出。这是因为time
不想干扰您可能执行的重定向或管道,这是一件好事。
要在标准输出上获得time
输出,您需要:
time stuff; 2>&1
(分组和重定向)。
现在,关于解析输出:解析命令的输出通常是一个坏主意,尤其是在可以不解析的情况下。幸运的是,Bash 的time
命令接受格式字符串。来自手册:
TIMEFORMAT
此参数的值用作格式字符串,指定应如何显示以时间保留字为前缀的管道的时间信息。
%
字符引入了一个转义序列,该序列扩展为时间值或其他信息。转义序列及其含义如下;大括号表示可选部分。
%%
A literal `%`.
%[p][l]R
The elapsed time in seconds.
%[p][l]U
The number of CPU seconds spent in user mode.
%[p][l]S
The number of CPU seconds spent in system mode.
%P
The CPU percentage, computed as (%U + %S) / %R.
可选的
p
是指定精度的数字,即小数点后的小数位数。值 0 导致不输出小数点或分数。最多可指定小数点后三位; p大于3的值改为3。如果没有指定p
,则使用值3。可选的
l
指定更长的格式,包括分钟,格式为MMmSS.FFs
。p
的值决定是否包含分数。如果没有设置这个变量,Bash 就好像它有值一样
$'\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS'
如果值为空,则不显示时间信息。显示格式字符串时添加尾随换行符。
所以,要完全实现你想要的:
var=$(TIMEFORMAT='%R'; time $ALGORITHM $VALUE $FILENAME; 2>&1)
正如@glennjackman 指出的那样,如果您的命令将任何消息发送到标准输出和标准错误,您也必须注意这一点。为此,需要一些额外的管道:
exec 3>&1 4>&2
var=$(TIMEFORMAT='%R'; time $ALGORITHM $VALUE $FILENAME 1>&3 2>&4; 2>&1)
exec 3>&- 4>&-
来源:BashFAQ032上精彩的Greg's wiki。
【讨论】:
@Struan,如果 $ALGORITHM 命令向标准输出发送任何内容,您需要添加1>/dev/null
之后 2>&1
@glennjackman 精彩 Greg's wiki: How can I redirect the output of time
to a variable or file?.
太棒了。我正要发布另一个关于为什么输出有点有趣的帖子,但你救了我。谢谢!
@glennjackman 你对$ALGORITHM
的输出是完全正确的。我已经添加了一个关于它的词。谢谢。
如果有人感兴趣,我最终使用它来创建时间复杂度图来分析我一直在编写的算法的性能。这是一个运行的例子:i.imgur.com/VmV7VjE.png 再次感谢大家的帮助!【参考方案2】:
您可以尝试以下 awk 命令,该命令使用 split 函数根据 digit m
或最后一个 s
拆分输入。
$ foo=$(awk '/^real/split($2,a,"[0-9]m|s$"); print a[2]' file)
$ echo "$foo"
0.435
【讨论】:
感谢您的帮助。到目前为止我已经尝试过了,但它会打印出原始输出,而不是 0.435 hastebin.com/ocogimesum.pl 注意time
的输出通常会进入stderr,所以你必须重定向。【参考方案3】:
你可以使用这个 awk:
var=$(awk '$1=="real"gsub(/^[0-9]+[hms]|[hms]$/, "", $2); print $2' file)
echo "$var"
0.435
【讨论】:
感谢@fedorqui,在 SO 上花费 4 年以上之后,您将拥有超过 200k 你需要特殊技能来处理这些数字,我会坐下来享受你的大师们:)恭喜! 注意time
的输出通常会到stderr,所以你必须重定向。以上是关于解析 Bash 内置时间的输出的主要内容,如果未能解决你的问题,请参考以下文章
使用 awk 解析 nm 命令的输出 - Linux Bash
如何删除 jq 输出中的双引号以在 bash 中解析 json 文件?