Thread Dateien durchsuchen (29 answers)
Opened by Paul at 2013-01-30 21:28

Linuxer
 2013-02-01 10:28
#165381 #165381
User since
2006-01-27
3891 Artikel
HausmeisterIn

user image
Was ist mit topegs Lösungsvorschlägen? Funktionieren die nicht?

Mein erster Ansatz war:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#! /usr/bin/perl
use strict;
use warnings;

use List::Util qw( first );

my $fileA         = "A.txt";
my $fileB         = "B.txt";
my $outfile       = "C.txt";
my $criteria_size = 20;


# be sure you have enough memory for this!
my @reference = do { open my $fh, '<', $fileB; <$fh> };

open my $fhout, '>', $outfile   or die "open($outfile,w) failed: $!\n";
open my $fhin, '<', $fileA      or die "open($fileA,ro) failed: $!\n";

while ( my $lineA = <$fhin> ) {

    my $critA = substr( $lineA, 0, $criteria_size );

    # return first line with matching reference number and leave it in @reference
    my $lineB = first { substr( $_, 0, $criteria_size ) == $critA } @reference;
    print $fhout ( $lineB ? $lineB : $lineA );
}

close $fhin;
close $fhout                    or die "close($outfile) failed: $!\n";


Mein zweiter Ansatz benutzt einen Hash, wie von topeg und Muffi schon eingesetzt:

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#! /usr/bin/perl
use strict;
use warnings;

use List::Util qw( first );

my $fileA         = "A.txt";
my $fileB         = "B.txt";
my $outfile       = "C.txt";
my $criteria_siue = 20;

# be sure you have enough memory for this!
my %reference;

open my $fh, '<', $fileB    or die "open($fileB,ro) failed: $!\n";
# expensive in memory usage (as it uses temporary lists in memory)
# %reference = map { substr( $_, 0, $criteria_size ) => $_  } <$fh>;

while ( my $line = <$fh> ) {
    $refernce{ substr( $line, 0, $criteria_size ) } = $line;
}
close $fh;

open my $fhout, '>', $outfile   or die "open($outfile,w) failed: $!\n";
open my $fhin, '<', $fileA      or die "open($fileA,ro) failed: $!\n";

while ( my $lineA = <$fhin> ) {

    my $critA = substr( $lineA, 0, $criteria_size);

    print $fhout ( exists $reference{$critA} ? $reference{$critA} : $lineA );
}

close $fhin;
close $fhout                    or die "close($outfile) failed: $!\n";


Beide setzen voraus, dass ausreichend Speicher vorhanden ist, um Datei B vollständig in den Speicher zu laden.

Mein Test mit einer Datei A mit 500 Zeilen (Kennzahl ist 5 Zeichen breit) und einer Datei B mit 1000 Zeilen braucht solange:

Code: (dl )
1
2
3
4
5
6
7
8
9
# Variante 1
real 0m0.286s
user 0m0.284s
sys 0m0.001s

# Variante 2
real 0m0.018s
user 0m0.011s
sys 0m0.005s


edit:
- beide Codes editiert; $criteria_size eingesetzt.
- Code editiert in Beispiel 2; Referenz-Hash wird nun zeilenweise aufgebaut
Last edited: 2013-02-01 13:52:18 +0100 (CET)
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!

View full thread Dateien durchsuchen