линии grep, соответствующие шаблону, и строки до и после соответствия - PullRequest
3 голосов
/ 06 марта 2012

Я хотел бы выполнить сопоставление с образцом в файле (около 200 мегабайт), а затем вставить в массив совпадающие строки, а также произвольное количество строк до и после каждой совпадающей строки.

sub1,использование perl grep, занимает 11 секунд

sub2, который использует unix egrep, 1 секунду

sub6 (ack) 50 секунд (это быстрее, если вы не используете якоря \ b, \ sи т. д.)

ack из командной строки занимает 15 секунд

Меня интересуют предложения по ускорению sub1 или поиску быстрого решения perl, которое не зависит от внешнегоtools

Кажется, что perl grep намного медленнее, чем unix.

"index" действительно быстрее, чем регулярные выражения (но мне нужны \ b, \ s и т. д.)

http://www.perlmonks.org/?node_id=885174

http://www.perlmonks.org/?node_id=957554

спасибо

use 5.014;
use strict;
use warnings;
use Time::HiRes qw(usleep ualarm gettimeofday tv_interval);
use List::MoreUtils qw(uniq);

open FILE, '<textMatchInAfile.txt' or die;
my $p = '\bsala|che|relazione|di|questo|coso|^qui\$';
my $mR = 1;        #print more rows before - after the matching
my @n  = <FILE>;

&sub1( $p, $mR, @n );    #suggest: insert references
&sub3( $p, $mR );

sub sub1 {               #questa sub usa perl grep
my $p    = $_[0];             #pattern
my $mR   = $_[1];             #more rows
my @n    = @_[ 2 .. $#_ ];    #input File
my $time = [gettimeofday];
my @new = grep { $n[$_] =~ /$p/ } 0 .. $#n;
my @unique =
  map { @n[ $_ - $mR .. $_ + $mR ] } @new[ 0 + $mR .. $#new - $mR];
say "\n" . 'time sub1 perl grep: ' . tv_interval($time);
@unique = uniq(@unique);
say "sub 1 $#unique";
}

sub sub3 {    #unix grep with color and line numbers
my $p   = $_[0];
my $mR  = $_[1];
my $cmd = "grep -n -C $mR";    #with line numbers
$p =~ s/\|/ /g;
$p =~ s/\h+/" -e "/g;
$p = ' -e "' . $p . '" ';
say "cmd ===$cmd=== ss ===$p===";
my @values;
$values[0] = $p;
$values[1] = ( ' ' . 'textMatchInAfile.txt' );    
my $time = [gettimeofday];
my @valori = `$cmd @values` or die "system @values` failed: $?";
say 'sub3 egrep shell: ' . $#valori;
say 'time sub3 tempo trovati con egrep shell ' . tv_interval($time);
my @uniq_list = uniq(@valori);
}

sub sub6 {             #perl ack
my $p  = $_[0];    #pattern
my $mR = $_[1];    #more rows
my @values;
my $time   = [gettimeofday];
my @valori = qx (ack -C $mR "$p" textMatchInAfile.txt)
  or die "system @values` failed: $?";
say 'number of values found with ack' . $#valori;
say 'time sub6 ack' . tv_interval($time);
}
#
#this one takes 11 seconds

 use 5.014;
 use warnings;
 use Time::HiRes qw(usleep ualarm gettimeofday tv_interval);

 my @array;
 my $pattern = '\bsala|che|relazione|di|questo|coso|^qui\$';
 open( my $filehandle, "<textMatchInAfile.txt" );
 my $time = [gettimeofday];
 while (<$filehandle>) {
     if ( $_ =~ /$pattern/ ) {
    push @array;
     }
 }
 say 'time while' . tv_interval($time);

ОК, Unix grep на порядокбыстрее, чем Perl Grep, я буду жить с этим.

Ответы [ 2 ]

3 голосов
/ 06 марта 2012

Почему вы не используете grep -B 1 -A 1?

Это даст вам точный вывод, который вам нужен.

grep -B 1 -A 1 -E patter file

С уважением,

1 голос
/ 14 марта 2012

Я провел некоторое базовое сравнение Unix 'egrep и команды Perl grep, последняя с двумя различными реализациями.

use Benchmark qw(cmpthese);

my $count = $ARGV[0] || 100;

my $re = "L[aeiou]n*.?[xyz]\\b";

cmpthese($count, {
    unix => sub {
        my $result = `dmesg|egrep '$re'`;

        #print "===unix===\n";
        #print $result;
    },
    perl => sub {
        my @result = grep {$_ =~ m/$re/} split m/\n/, `dmesg`;

        #print "===perl===\n";
        #map {print "$_\n"} @result;
    },
    perl2 => sub {
        open(DMESG, "dmesg|" ) or die "cannot open dmesg pipe!";

        my @result;

        while(<DMESG>) {
            push @result, $_ if m/$re/;
        }

        #print "===perl2===\n";
        #map {print} @result;

        close DMESG;
    },
});

Результат:

$ perl grep.pl 1000
        Rate  unix  perl perl2
unix  24.6/s    --  -40%  -44%
perl  41.0/s   67%    --   -6%
perl2 43.6/s   77%    6%    --

Поэтому, пожалуйста, объясните, почему grep в Perl, естественно, медленнее, чем Unix grep.

PS. Я адаптировал скрипт для работы с файлом с 25 тыс. Строк случайных данных и другим RE.Этот сценарий немного похож на ваш.

$ perl tmp/grep.pl 1000
        Rate  unix  perl perl2
unix  3.71/s    --  -32%  -44%
perl  5.50/s   48%    --  -17%
perl2 6.64/s   79%   21%    --
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...