bash 如何在bash脚本中存储“时间”函数输出的子字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4457953/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to store a substring of the output of "time" function in bash script
提问by Tony Stark
So the built-in time function for bash should output in this format
所以bash的内置时间函数应该以这种格式输出
real 0m0.002s
user 0m0.001s
sys 0m0.000s
I want to save the user time in milliseconds, like 001 what's a clean way to do this?
我想以毫秒为单位保存用户时间,比如 001 有什么干净的方法可以做到这一点?
回答by wnoise
The clean way is to use the TIMEFORMATshell variable to only print the user information. (man bashfor more details.)
干净的方法是使用TIMEFORMATshell变量只打印用户信息。(man bash了解更多详情。)
Then, of course you need to capture the output from it. This is impossible to do from the pipeline, as it's done internally by the shell, but you can run it in a subshell, and the output will go to standard error. But then you have to somehow redirect the output of the command elsewhere. Here, I just discard it, but many other possibilities exist, depending on exactly what you need to do. Then you need to munge d.dddinto dddd. Just deleting the period will do so.
然后,当然您需要从中捕获输出。这是不可能从管道中完成的,因为它是由 shell 在内部完成的,但是您可以在子 shell 中运行它,并且输出将转到标准错误。但是你必须以某种方式将命令的输出重定向到其他地方。在这里,我只是放弃了它,但存在许多其他可能性,具体取决于您需要做什么。然后你需要d.ddd进入dddd. 只需删除句点即可。
(TIMEFORMAT="%U"; time ls > /dev/null) |& tr -d .
If you like, you can add | sed s/^0*//to eliminate the leading zeroes.
如果您愿意,可以添加| sed s/^0*//以消除前导零。
%R will give real time, %S system time. You can change the precision with e.g. %6U to get microseconds, though most systems won't be anywhere near that accurate.
%R 将给出实时,%S 系统时间。您可以使用例如 %6U 更改精度以获得微秒,尽管大多数系统不会接近该精度。
man bashfor help on redirections. man trand man sedfor help on how to use them.
man bash寻求有关重定向的帮助。 man tr以及man sed如何使用它们的帮助。
回答by SiegeX
Bash's timebuiltin is a bit tricky to capture because it has special handling so that it can return the processing time for an entire pipeline like time ls -l | sort | uniqrather than just the processing time for only the ls -lcommand in my example.
Bash 的time内置函数有点难以捕获,因为它具有特殊的处理方式,因此它可以返回整个管道time ls -l | sort | uniq的处理时间,而不仅仅是ls -l我示例中的命令的处理时间。
The best way to capture justthe output of time is the following redirection technique:
仅捕获时间输出的最佳方法是以下重定向技术:
exec 3>&1 4>&2
foo=$( { time some_command 1>&3 2>&4; } 2>&1 ) # change some_command
exec 3>&- 4>&-
At this point if you were to echo "$foo"you would see something on the order of
在这一点上,如果你愿意,echo "$foo"你会看到一些东西
real 0m0.013s
user 0m0.004s
sys 0m0.007s
Now to get just the 004part of that you have quite a few options: sed, awk or straight bash to name the top 3. My personal favorite would be awk and it would look something like this:
现在要了解其中的004一部分,您有很多选择:sed、awk 或直接 bash 来命名前 3 名。我个人最喜欢的是 awk,它看起来像这样:
foo=$({ time some_command 1>&3 2>&4;} 2>&1 | awk -F'[s.]' '/user/{print }')
Now if you were to echo "$foo"you would see just 004as desired
现在,如果你愿意,echo "$foo"你会看到你004想要的
回答by gnarf
Using bash's built in string globbing you could do something like this:
使用 bash 的内置字符串通配符,您可以执行以下操作:
output="real 0m0.002s
user 0m0.001s
sys 0m0.000s"
#get everything to the right of first "*user "
user=${output#*user }
#get everything to the left of the first "s*"
user=${user%%s*}
#get everythig to let left of "m*"
min=${user%%m*}
#get everything to the right of "*m" and left of ".*"
sec=${user#*m}
sec=${sec%%.*}
#get everything to the right of "*."
usec=${user#*.}
time=$[$usec + $sec * 1000 + $min * 60000]
Results running bash -x
结果运行 bash -x
+ output='real 0m0.002s
user 0m0.001s
sys 0m0.000s'
+ user='0m0.001s
sys 0m0.000s'
+ user=0m0.001
+ min=0
+ sec=0.001
+ sec=0
+ usec=001
+ time=1

