【问题标题】:Struggling to parse (bash) time command努力解析(bash)时间命令
【发布时间】:2011-04-25 02:43:21
【问题描述】:

我正在努力解析 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 的形式。我目前不知道如何抑制“时间”输出,将其全部捕获而不是空白行,也不知道如何解析它以获得我需要的值。

任何帮助将不胜感激......

【问题讨论】:

    标签: bash time


    【解决方案1】:

    time 命令将计时信息输出到 STDERR,您不会捕获或重定向这些信息。因此,在赋值时,该信息被打印到您的控制台,而$TIME 变量获取命令的 STDOUT - 您重定向到 /dev/null,所以它是空白的。

    也许您应该尝试捕获命令的 STDERR?

    【讨论】:

    • 啊,我没有意识到那个时间输出到STDERR。那么如何将其捕获到$TIME 变量中呢?
    【解决方案2】:

    首先,您尝试捕获的数据正在写入标准错误。但在这种情况下,捕获该输出相当棘手。

    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 上写入标准错误的内容,从而允许您捕获输出。有关子外壳的更多信息,请参阅http://www.tldp.org/LDP/abs/html/subshells.html

    【讨论】:

    • 或者只使用一个子shell为TIME="$( { time ls -lh >/dev/null; } 2>&1)
    【解决方案3】:

    如果您使用 Bash 内置 time,您可以通过设置 TIMEFORMAT 变量来控制其输出:

    TIMEFORMAT=%R
    

    您不必进行任何解析,因为这将导致time 仅输出秒数。

    并使用它:

    echo "Testing..."
    TIME=$( { time ls -lh > /dev/null; } 2>&1 )
    echo $TIME
    

    或来自BashFAQ/032 的其他技术之一。

    【讨论】:

      【解决方案4】:

      我想将此作为评论发布,但太长了。我想介绍另一种略有不同的数据获取方式。

      您可以使用两个子 shell 以流的形式获取时间输出,使用 /bin/sh 而不是 /usr/bin/time 来获取执行时间。我想你可以在这里用/usr/bin/time 替换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' 
      

      修正格式。

      【讨论】:

        【解决方案5】:

        虽然解决方案围绕相同的逻辑徘徊,但我仍然找不到以下列出的,所以另一个版本的解决方案:

        TIME=$(time (ls -lh >/dev/null) 2>&1)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-02-16
          • 2017-11-09
          • 1970-01-01
          • 2020-11-09
          • 1970-01-01
          • 2016-01-14
          • 1970-01-01
          相关资源
          最近更新 更多