我有一个脚本调用Perl的Time :: HiRes模块来计算经过的时间。 基本上,脚本通过传递以下单行来获得时间:
use Time::HiRes qw(time); print time
通过后退标记到Perl解释器并获取结果。
#/bin/sh
START_TIME=`perl -e 'use Time::HiRes qw(time); print time'`
END_TIME=`perl -e 'use Time::HiRes qw(time); print time'`
ELAPSED_TIME=$(echo "($END_TIME - $START_TIME)" | bc)
echo $ELAPSED_TIME
我尝试以更模块化的方式重写它,但是我被bash shell的引用规则所困扰。
#/bin/sh
CALCULATE='bc'
NOW="perl -e 'use Time::HiRes qw(time); print time'"
START_TIME=`$NOW`
[Some long running task ...]
ELAPSED_TIME=$(echo "($NOW - $START_TIME)" | $CALCULATE)
echo $ELAPSED_TIME
Bash抱怨没有正确引用某些内容。为什么bash只是在$ NOW中扩展命令并将其传递给后面的tick来执行?
我尝试了各种方法在shell脚本变量中嵌入perl代码,但似乎无法得到它 对。
任何人都知道如何正确引用shell脚本中的perl代码?
答案 0 :(得分:7)
使用函数是最简单的方法,我认为:
#! /bin/bash
now() {
perl -e 'use Time::HiRes qw(time); print time';
}
calc=bc
time1=$(now)
time2=$(now)
elapsed=$(echo $time2 - $time1 | $calc)
echo $elapsed $time1 $time2
基本上不需要引用。
答案 1 :(得分:3)
您的问题是$NOW
只是一个包含一些perl代码的字符串。您需要告诉bash执行它,使用反引号或$()
:
ELAPSED_TIME=$(echo "($($NOW) - $START_TIME)" | $CALCULATE)
另外,bash可以本地运算:
ELAPSED_TIME=$(( $($NOW) - $START_TIME))
无需调用bc
。
最后,启动和停止perl可能需要花费大量时间,这会给结果增加噪音。我建议只运行一次perl,并让perl本身执行长时间运行的任务。然后你也可以在perl中完成所有的计算:
#!/usr/bin/perl
use Time::HiRes qw(time);
my $start = time;
system(@ARGV);
my $end = time;
print "Elapsed: ", ($end - $start), "\n"
或者您可以直接使用bash内置time
(或/usr/bin/time
)来完成所有时间。
答案 2 :(得分:1)
如果$NOW
超出引号,则会在空格上拆分。
$ perl -E'say 0+@ARGV; say for @ARGV' $NOW
7
perl
-e
'use
Time::HiRes
qw(time);
print
time'
您可以用双引号括起变量以避免这种情况:
$ perl -E'say 0+@ARGV; say for @ARGV' "$NOW"
1
perl -e 'use Time::HiRes qw(time); print time'
但是您希望将该字符串作为shell命令执行。为此,请使用eval
。
$ eval "$NOW"
1335602750.57325
最后,为了分配它,我们使用反引号(或等效的$( ... )
)。
$ START_TIME=$(eval "$NOW")
$ echo $START_TIME
1335602898.78472
以前发布的功能显然比较清晰,但是你说你想要引用帮助。
顺便说一下,
perl -e 'use Time::HiRes qw(time); print time'
可以缩短为
perl -MTime::HiRes=time -e'print time'
甚至以下(因为尾随新行完全正常):
perl -MTime::HiRes=time -E'say time'
或者如果你真的想打高尔夫球:
perl -MTime::HiRes=time -Esay+time
答案 3 :(得分:0)
下面是你的脚本的修改版本,你基本上需要了解一些应用程序有标准输出朝向stderr(标准错误)所以当你没有看到他们的输出放入变量时你只需要将它重定向到stdout(标准输出p)
#/bin/sh
CALCULATE='bc'
echo 'starting'
NOW=$(perl -e 'use Time::HiRes qw(time); print time' 2>&1)
sleep 3
echo 'ending'
END_TIME=$(perl -e 'use Time::HiRes qw(time); print time' 2>&1)
ELAPSED_TIME=$(echo "($NOW - $START_TIME)")
echo $ELAPSED_TIME
答案 4 :(得分:0)
我认为使用HiRes时间的好处是因为perl是一个相对繁重的外部进程而且它被单独调用了两次。 如果您不需要该值的那么多小数位。你可以使用bash中内置的时间,如
task() {
[Some long running task ...]
}
TIMEFORMAT=%R
elapse=$({ time task > task.out 2>&1; } 2>&1)
echo $elapse