简体   繁体   English

在反引号中使用date命令的perl

[英]perl with the date command in backticks

There are a bunch of scripts - actually all the Perl scripts in this shop that use a date - use this kind of structure. 有一堆脚本 - 实际上这个商店中使用日期的所有Perl脚本 - 都使用这种结构。 It uses the date command in backticks. 它在反引号中使用date命令。 Is this really bad? 这真的很糟糕吗? Does it open up a subshell or something, or is just not 'perlish'. 它是打开子壳还是其他东西,或者只是不是'perlish'。 Is it worth me going though all the scripts in the SVN and changing this to localtime? 是否值得我浏览SVN中的所有脚本并将其更改为本地时间?

#!/usr/bin/perl
chomp($date=`date '+%Y%m%d'`);
if (@ARGV) {
   $date = $ARGV[0] ;
}

Why not using perl's : 为什么不使用perl:

$ perl -MPOSIX -e 'print POSIX::strftime("%Y%m%d", localtime());'
20150106

? Your solution is all but perlish and it needs to fork() at low level 你的解决方案只是perlish而且需要fork()在低级别

This is a benchmark of the 3 solutions given : the code : 这是给出的3个解决方案的基准:代码:

#!/usr/bin/env perl
use strict; use warnings;

use Benchmark qw(:all) ; 
use autodie;

open my $daveNull, ">", "/dev/null";

my $results = timethese(my $count, {
    'POSIX'         => sub {
        use POSIX;
        print $daveNull POSIX::strftime("%Y%m%d", localtime());
    },
    'Time::Piece'   => sub {
        use Time::Piece;
        print $daveNull localtime()->strftime('%Y%m%d');
    },
    'sysdate'       => sub {
        chomp(my $date=`date '+%Y%m%d'`);
        print $daveNull $date;
    },
});
print "-----8<-------------\n";
cmpthese( $results ) ;

OUTPUT : 输出:

Benchmark: running POSIX, Time::Piece, sysdate for at least 3 CPU seconds...
POSIX:  3 wallclock secs ( 2.14 usr +  1.06 sys =  3.20 CPU) @ 234115.94/s (n=749171)
Time::Piece:  3 wallclock secs ( 2.72 usr +  0.47 sys =  3.19 CPU) @ 68128.84/s (n=217331)
sysdate: 37 wallclock secs ( 0.36 usr  2.67 sys + 20.62 cusr  8.00 csys = 31.65 CPU) @ 285.91/s (n=9049)
-----8<-------------
                Rate     sysdate Time::Piece       POSIX
sysdate        286/s          --       -100%       -100%
Time::Piece  68129/s      23729%          --        -71%
POSIX       234116/s      81785%        244%          --

CONCLUSION 结论

POSIX is the winner. POSIX是赢家。

Or you could just use Time::Piece, which has been in Core since 5.009005. 或者你可以使用Time :: Piece,自从5.009005以来一直在Core中。

use Time::Piece;

then you can just 那么你可以

my $t = localtime;
print $t->strftime('%Y%m%d');

or 要么

use Time::Piece;
print localtime()->strftime('%Y%m%d');

This uses the strftime format, but has much less overhead than loading the entire POSIX extension. 这使用strftime格式,但是比加载整个POSIX扩展的开销要少得多。

Plus is has a bunch of preset formats, one of which is 'ymd' where you can specify the delimter... in this case, none Plus有一堆预设格式,其中一个是'ymd',您可以在其中指定分隔符...在这种情况下,没有

print localtime()->ymd("")

Check the perldoc for more examples. 检查perldoc以获取更多示例。

At minimum, only invoke the shell if you need to: 至少,只有在需要时才调用shell:

if (@ARGV) {
   $date = $ARGV[0] ;
}
else {
    chomp($date=`date '+%Y%m%d'`);
}

It's considerably less efficient to invoke the shell only to throw the result away. 调用shell只是为了抛弃结果,效率要低得多。

But you can generate the output with pure Perl — in multiple ways. 但是你可以用多种方式用纯Perl生成输出。 The Time::Piece module is a Perl core module, which means it is always there, or you could use strftime from one of the modules that provides it. Time::Piece模块是Perl核心模块,这意味着它始终存在,或者您可以从提供它的模块之一使用strftime

$ perl -MTime::Piece -le '$t = new Time::Piece; print $t->ymd("");'
20150106
$ perl -MTime::Piece -le '$t = localtime; print $t->ymd("");'
20150106
$ perl -MTime::Piece -le '$t = localtime; print $t->strftime("%Y%m%d")'
20150106
$ perl -MPOSIX -le 'print strftime("%Y%m%d", localtime(time))'
20150106
$

So, in context, and assuming you add use Time::Piece; 所以,在上下文中,假设你添加use Time::Piece; at the top of your file, you might write: 在文件的顶部,您可能会写:

use Time::Piece;

…

if (@ARGV) {
   $date = $ARGV[0] ;
}
else {
    my $t = localtime;
    $date = $t->ymd("");
}

This doesn't calculate a default date unless it is needed. 除非需要,否则不会计算默认日期。

Calling date like that will open a new shell environment, which is painfully inefficient. 像这样调用date将打开一个新的shell环境,这是非常低效的。 Try it with Benchmark and see just how bad it gets. 尝试使用Benchmark,看看它有多糟糕。

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;
use Time::Piece;
use POSIX 'strftime';

use Benchmark;

my $fmt = '%Y%m%d';

timethese(100_000, {
  backticks => sub {
    my $date = `date +$fmt`;
  },
  strftime => sub {
    my $date = POSIX::strftime($fmt, localtime);
  },
  timepiece => sub {
    my $date = localtime->strftime($fmt);
  },
});

And here's the output: 这是输出:

Benchmark: timing 100000 iterations of backticks, strftime, timepiece...
 backticks: 108 wallclock secs ( 4.26 usr 25.05 sys +  4.82 cusr 85.59 csys = 119.72 CPU) @ 835.28/s (n=100000)
  strftime:  1 wallclock secs ( 1.03 usr +  0.00 sys =  1.03 CPU) @ 97087.38/s (n=100000)
 timepiece:  1 wallclock secs ( 1.33 usr +  0.00 sys =  1.33 CPU) @ 75187.97/s (n=100000)

The backticks solution is about a hundred times slower than the other two options. 反引号解决方案比其他两个选项慢约一百倍。

But, of course, it works. 但是,当然,它有效。 And if you're not worried about the performance of the program then don't bother to change it. 如果你不担心程序的性能,那么就不用费心去改变它了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM