2017-05-09 1 views
-5

Mein Problem ist, wie mein Skript schnell zu machen (ich benutze große Dateien)Perl: script schnell macht große Datei verwenden

Ich habe das Skript darüber „bbb“ zwischen den Worten hinzufügen, wenn die Worte in einem anderen existieren Datei, die Sequenzen von Wörtern für exemple file2.txt enthalten: i eat big pizza .my big pizza ... file1.txt (Sequenzen):

      eat big pizza 
          big pizza 

das Ergebnis newFile

i eatbbbbigbbbpizza.my bigbbbpizza ... 

mein Skript:

use strict; 
use warnings; 
use autodie; 

open Newfile ,">./newfile.txt" or die "Cannot create Newfile.txt"; 
my %replacement; 
my ($f1, $f2) = ('file1.txt', 'file2.txt'); 

open(my $fh, $f1); 
my @seq; 
foreach (<$fh>) 
{ 
    chomp; 
    s/^\s+|\s+$//g; 
    push @seq, $_; 
} 
close $fh; 

@seq = sort bylen @seq; 

open($fh, $f2); 
foreach (<$fh>) { 
    foreach my $r (@seq) { 

    my $t = $r; 
    $t =~ s/\h+/bbb/g; 

    s/$r/$t/g; 
    } 
    print Newfile ; 
} 
close $fh; 
close Newfile ; 
exit 0; 

sub bylen { 
    length($b) <=> length($a); 
} 

Antwort

0

anstelle eines Arrays

my @seq; 

Ihre Worte als Hash definieren.

my %seq; 

Statt

push @seq, $_; 

speichern die Wörter in der Hash die Worte drücken. Berechnen Sie den Ersatz vor und entfernen Sie ihn aus der Schleife.

my $t = $_; 
$t =~ s/\h+/bbb/g; 
$seq{$_} = $t; 

vorberechnen die Worte vor der äußeren Schleife:

my @seq = keys %seq; 

Und Hash-Lookups verwenden Sie den Ersatz in der inneren Schleife zu finden:

my $t = $seq{$r}; 

Dies könnte ein etwas schneller, aber erwarte nicht zu viel.

In den meisten Fällen ist es besser, das Problem zu reduzieren, indem die Eingabe auf eine Weise vorbereitet wird, die die Lösung vereinfacht. Zum Beispiel ist grep -f viel schneller als Ihre Perl-Loops. Verwenden Sie grep, um die Linien zu finden, die ersetzt werden müssen, und ersetzen Sie sie mit Perl oder Sed.

Eine andere Möglichkeit besteht darin, den Job zu parallelisieren. Sie können Ihre Eingabe in n Teile teilen und n Prozesse auf n CPUs parallel ausführen. Siehe die GNU parallel tutorial.

0

Was ist ein regulärer Ausdruck wie folgt aus (Vorsicht, dass dieser Ansatz Sicherheitsbedenken führen kann)?

use strict; 
use warnings; 

open (my $Newfile, '>', 'newfile.txt') or die "Cannot create Newfile.txt: $!"; 
my ($f1, $f2) = qw(file1.txt file2.txt); 

open (my $fh, $f1) or die "Can't open $f1 for reading: $!"; 
my @seq = map {split ' ', $_ } <$fh>; 
close $fh; 
# an improvement would be to use an hash to avoid dupplicates 

my $regexp = '(' . join('|', @seq) . ')'; 

open($fh, $f2) or die "Can't open $f2 for reading: $!"; 
foreach my $line (<$fh>) { 
    $line =~ s/$regexp/$1bbb/g; 
    print $Newfile $line; 
} 
close $fh; 
close $Newfile ; 
exit 0;