在perl中直接替换或匹配并替换

时间:2013-07-01 18:02:54

标签: perl

有一个包含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...
}

在速度(和正确性)方面无关紧要......

2 个答案:

答案 0 :(得分: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个字符串的连续序列出现。这不会模拟实际数据,这更加随机。

答案 1 :(得分:0)

你想删除前十四个字符吗?

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

作为Perl程序员,我们已经调整为正则表达式,我们有时会忘记非正则表达式的做法,而这些通常更快。

使用

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

使用Benchmark模块并查看。