如何在bash脚本中存储"time"函数输出的子字符串

Ton*_*ark 7 regex linux bash time

所以bash的内置时间函数应该以这种格式输出

real 0m0.002s
user 0m0.001s
sys  0m0.000s
Run Code Online (Sandbox Code Playgroud)

我想以毫秒为单位节省用户时间,比如001什么是干净的方法呢?

Sie*_*geX 11

Bash的time内置捕获有点棘手,因为它具有特殊的处理能力,因此它可以返回整个管道time ls -l | sort | uniq的处理时间,而不仅仅是ls -l我的示例中的命令的处理时间.

捕捉到最好的办法只是时间的输出如下重定向技术:

exec 3>&1 4>&2
foo=$( { time some_command 1>&3 2>&4; } 2>&1 ) # change some_command
exec 3>&- 4>&-
Run Code Online (Sandbox Code Playgroud)

在这一点上,如果你去,echo "$foo"你会看到的顺序

real    0m0.013s
user    0m0.004s
sys     0m0.007s
Run Code Online (Sandbox Code Playgroud)

现在只是为了获得004一部分,你有很多选择:sed,awk或直接bash来命名前3名.我个人最喜欢的是awk,看起来像这样:

foo=$({ time some_command 1>&3 2>&4;} 2>&1 | awk -F'[s.]' '/user/{print $3}')
Run Code Online (Sandbox Code Playgroud)

现在,如果你去,echo "$foo"你会看到004所希望的


wno*_*ise 10

干净的方法是使用TIMEFORMATshell变量只打印用户信息.(man bash更多细节.)

然后,当然你需要捕获它的输出.这是不可能从管道执行的,因为它是由shell内部完成的,但您可以在子shell中运行它,输出将转到标准错误.但是你必须以某种方式将命令的输出重定向到其他地方.在这里,我只是丢弃它,但是存在许多其他可能性,具体取决于你需要做什么.然后你需要d.ddd进入dddd.只删除期限即可.

(TIMEFORMAT="%U"; time ls > /dev/null) |& tr -d .
Run Code Online (Sandbox Code Playgroud)

如果您愿意,可以添加| sed s/^0*//以消除前导零.

%R将给出实时,%S系统时间.您可以使用%6U更改精度以获得微秒,但大多数系统都不会接近那么准确.

man bash有关重定向的帮助. man tr以及man sed如何使用它们的帮助.


gna*_*arf 1

使用 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]
Run Code Online (Sandbox Code Playgroud)

结果运行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
Run Code Online (Sandbox Code Playgroud)