![Bash 时间命令输出与环境变量赋值不同](https://linux22.com/image/1610448/Bash%20%E6%97%B6%E9%97%B4%E5%91%BD%E4%BB%A4%E8%BE%93%E5%87%BA%E4%B8%8E%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E8%B5%8B%E5%80%BC%E4%B8%8D%E5%90%8C.png)
通常该time
命令输出三行:
> time sleep 2
real 0m2.003s
user 0m0.000s
sys 0m0.006s
但是,当加上变量赋值后,输出将变成一行:
> VAR="" time sleep 2
0.00user 0.00system 0:02.00elapsed 0%CPU (0avgtext+0avgdata 2060maxresident)k
0inputs+0outputs (0major+86minor)pagefaults 0swaps
为什么会发生这种情况?有没有办法在输出三行的同时保留变量赋值?
答案1
为什么会发生这种情况?
在 Bash 中time
有一个保留字 (关键词) 不仅可以放在简单命令之前进行测量,还可以测量管道。因此,它必须是第一个词。此语法仅通知 Bash 您想要测量时间;管道的其余部分仍由 Bash 处理,就像time
不存在一样。
如果time
不是第一个单词,但仍然可以解释为命令,则将其解释为常规外部命令(甚至不是内置命令),查找$PATH
并执行;例如它可以是/usr/bin/time
。此工具处理其参数并从中构建实际命令。
这两个实用程序产生不同格式的输出。
有没有办法在将输出分为三行的同时保留变量赋值?
是的。您可以将其用作time
第一个单词,这样它就会被解释为关键字:
time VAR="" sleep 2
注意,两种实现都支持-p
将输出格式更改为由 POSIX 指定(事实上-p
POSIX 要求它本身的支持)。这意味着以下两个命令将产生相同格式的输出:
time -p VAR="" sleep 2
VAR="" time -p sleep 2
然而,从本质上讲,它们是非常不同的。
答案2
时间将其输出发送到 STDERR 而不是 STDOUT。
有几个选项,但我不清楚您计划如何使用捕获的数据,所以我将把它分成三行。
$ narf="$( ( time sleep 2 ) 2>&1 )" ; echo "${narf}" ; unset narf
real 0m2.002s
user 0m0.001s
sys 0m0.001s
$ narf="$( ( time sleep 5 ) 2>&1 )" ; echo "${narf}" ; unset narf
real 0m5.002s
user 0m0.001s
sys 0m0.001s
$ narf="$( ( time -p sleep 5 ) 2>&1 )" ; echo "${narf}" ; unset narf
real 5.00
user 0.00
sys 0.00
前两个选项不使用 -p 格式选项(该选项设计用于符合 POSIX 标准)。第三个选项则使用 -p 格式选项。
如您所见,输出略有不同。如果您愿意,可以问我问题。(您可以删除 unset 命令,因为我使用它来执行多个测试。)