我正在努力解析bash中time命令的输出 - 甚至在我调用它时阻止它打印输出。这是我的测试代码:
#!/bin/bash
TIME=`time ls -lh > /dev/null`
echo "Testing..."
echo $TIME
目前打印出来:
{blank-line}
real 0m0.064s
user 0m0.002s
sys 0m0.005s
Testing
{blank-line}
因此,分配给$TIME
的值似乎是打印输出开始时的空白行。我需要得到sys系列的秒值 - 即“0.005”。我保证我将只有秒,所以我不需要任何“m”之前的任何东西 - 但是,如果它> = 10秒,秒部分可能是xx.xxx的形式。我目前不知道如何抑制'时间'输出,捕获所有输出而不是空白行,也不解析它以获得我需要的值。
非常感谢任何帮助......
答案 0 :(得分:18)
如果您使用Bash内置time
,则可以通过设置TIMEFORMAT
变量来控制其输出:
TIMEFORMAT=%R
并且您不必进行任何解析,因为这会导致time
仅输出秒数。
并使用此:
echo "Testing..."
TIME=$( { time ls -lh > /dev/null; } 2>&1 )
echo $TIME
或来自BashFAQ/032的其他技术之一。
答案 1 :(得分:7)
首先,您尝试捕获的数据正在写入标准错误。但在这种情况下捕获输出是相当棘手的。
time
既是可执行文件(在/usr/bin
中),也是bash和其他shell中的内置shell命令。在未指定time
的情况下执行/usr/bin/time
时,您正在bash中执行内置命令。这使得输出很难做到,因为bash并不像普通程序那样对待它;它是由bash编写的一个特殊的内置函数。
知道这一点,并查看time(1)
的手册页,我可以看到您尝试从time
捕获的数据输出到stderr。所以我的解决方法是直接执行/usr/bin/time
,如下所示:
TIME=`/usr/bin/time ls -lh 2>&1 >/dev/null`
这会将标准错误流复制到标准输出,然后将标准输出通常重定向到/dev/null
。但是,标准错误仍将标准化,因为它在重定向之前是重复的。颠倒这些顺序是行不通的。 (是的,这很令人困惑。)
不幸的是,/usr/bin/time
的输出精确度稍低:
0.00 real 0.00 user 0.00 sys
或者,您可以使用2个子shell,如下所示:
TIME=$((time ls -lh >/dev/null) 2>&1)
这将重写第一个shell中第二个子shell上写入标准错误的内容,允许您捕获输出。有关子shell的更多信息,请参阅http://www.tldp.org/LDP/abs/html/subshells.html。
答案 2 :(得分:2)
虽然解决方案徘徊在相同的逻辑上,但我仍然无法找到以下列出的内容,因此解决方案的另一个版本:
TIME=$(time (ls -lh >/dev/null) 2>&1)
答案 3 :(得分:1)
time
命令将时序信息输出到STDERR,您没有捕获或重定向。因此,在赋值时,该信息将打印到您的控制台,而$TIME
变量获取命令的STDOUT - 您重定向到/dev/null
,所以它是空白的。
也许您应该尝试捕获命令的STDERR?
答案 4 :(得分:0)
我想将此作为评论发布,但这会太长。我想提出另一种稍微不同的方法来获取数据。
您可以使用两个子shell将时间输出作为流使用/bin/sh
而不是/usr/bin/time
来获取执行的时间。我想你可以用time
替换/usr/bin/time
。
$ ((time ./print_test.sh > deleteme) 2>&1) > deletemetime
$ cat deleteme
test
$ cat deletemetime
./print_test.sh > deleteme 0.00s user 0.00s system 86% cpu 0.003 total
$ ((time ./print_test.sh > deleteme) 2>&1) | sed 's/system/kernel/'
./print_test.sh > deleteme 0.00s user 0.00s kernel 86% cpu 0.003 total
另请注意,它产生输出的方式似乎有所不同。有时它采用这种格式,有时采用这种格式:
real 0m0.420s
user 0m0.385s
sys 0m0.040s
此时不确定是什么决定了这种或那种方式。
当然,您可以使用例如
TIMEFORMAT='%3R'
修复格式。