2

有一个包含 milions++ 行的文件。有些行的形式是

123456_654321_some-random-text ( e.g. /\d{6}_\d{6}_(.*)/ )

其他人只是

some-random-text

和其他人再次不同......

从我的第一个示例中删除前 14 个字符的最快方法是什么?

while(<>) {
    chomp;
    s/^\d{6}_\d{6}_//;  # so simple trying to substitute from every line
                        # and substitute will fail anyway when doesn't match
}

或者

while(<>) {
    chomp;
    s/^.{14}// if m/^\d{6}_\d{6}_/;  # with condition...
}

就速度(和正确性)而言,这并不重要......

4

2 回答 2

4

它与您使用的内容几乎无关。您可以运行此基准测试:

$ perl <<'END'
use strict;
use warnings;
use Benchmark qw ( :all );

my @str = ('123456_654321_some-random-text' x 100, 'some text' x 50);

cmpthese( 3_000_000, {
     'regex'  => sub { map s/^\d{6}_\d{6}_//,                 @str; },
     'regex1' => sub { map /^\d{6}_\d{6}_/ && s/^.{14}//,     @str; },
     'split'  => sub { map /^\d{6}_\d{6}_/ && (split /_/)[2], @str; },
     'substr' => sub { map /^\d{6}_\d{6}_/ && substr($_, 14), @str; },
});
END

对我来说,对于如此少量的迭代,这会产生不确定的结果。结果还取决于月相和匹配线与不匹配线的比率(此处:2:1,但也可能是1:3)。

一般来说,我更喜欢s/^\d{6}_\d{6}_//,因为这会导致工作重复最少,并且是最清晰易读的内容。

在运行更长的基准测试时

my @str = ('123456_654321_some-random-text' x 100, 'some text' x 50)x100;

我得到以下结果:

          Rate  split regex1 substr  regex
split  39139/s     --   -12%   -14%   -18%
regex1 44603/s    14%     --    -2%    -7%
substr 45338/s    16%     2%     --    -5%
regex  47740/s    22%     7%     5%     --

它更喜欢这种简单的替换。但substr也不甘落后。然而,这些基准是相当人为的:只有一个匹配的字符串和一个不匹配的字符串,它们出现在 50-100 个字符串的连续序列中。这不会对实际数据进行建模,实际数据要随机得多。

于 2013-07-01T20:15:11.603 回答
0

您要删除前十四个字符吗?

我敢打赌,这substr将比正则表达式匹配更快。

作为 Perl 程序员,我们非常喜欢正则表达式,我们有时会忘记非正则表达式的处理方式,而这些方式通常更快。

使用

while( my $line = <> ) {
    chomp $line;
    $line = substr($line, 14);
}

使用基准模块并查看。

于 2013-07-01T19:20:22.833 回答