Thread Lesen Zeilen von einer Datei, verändern Zeilen in einer zweiten Datei
(9 answers)
Opened by bora99 at 2016-11-22 11:45
Wie groß sind denn die Report-Dateien? Ein paar Kilobytes? Megabytes? Gigabytes?
Wie viele Daten davon würden in eine Status-Datei geschrieben werden? Wenn das Kilobytes oder Megabytes sind, dann könnte man die Status-Infos erstmal in einer Variablen zwischenspeichern. Das würde die Vergleiche beschleunigen. In die Status-Datei wird dann nur geschrieben, wenn die aktuellen Werte noch nicht gesehen wurden. Oder Du verwendest das Modul Tie::File um die Status-Datei als Array einzubinden. Das senkt zwar nicht die notwendigen Zugriffe auf die Festplatte, aber es entlastet Dich von der Mühe, die Datei selber zu lesen und zu schreiben. Variante 1: 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 36 37 38 39 40 41 42 43 44 45 46 47 48 #! /usr/bin/env perl use strict; use warnings; use 5.010; die "Usage: $0 report status\n" if 2 != @ARGV; my $report_file = shift @ARGV; my $status_file = shift @ARGV; # hash for lookup of already seen datasets my %seen; # open report for reading open my $rfh, '<', $report_file or die "open($report_file,<) failed: $!"; # open status for writing (appending), change to > for overwriting open my $wfh, '>>', $status_file or die "open($status_file,>>) failed: $!"; LINE: while ( my $line = <$rfh> ) { warn "(D) read: $line\n"; # skip empty lines next LINE if $line =~ m/^\s*$/; chomp $line; # split into fields my ( $field1, $field2, $date1, $date2 ) = split m/\t/, $line; # no action if "date2" is not "-"; read next line next LINE if $date2 ne '-'; # prepare a string to compare from first three fields my $to_save = join "\t", $field1, $field2, $date1; # check dataset (and register it). If not yet seen, write it to status file if ( ! $seen{ $to_save }++ ) { say $wfh $to_save; } } close $wfh or die "close($status_file) failed: $!;"; close $rfh; __END__ Variante 2: 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 36 37 38 39 40 41 42 43 44 45 46 47 48 #! /usr/bin/env perl use strict; use warnings; use 5.010; use List::Util qw( first ); use Tie::File; die "Usage: $0 report status\n" if 2 != @ARGV; my $report_file = shift @ARGV; my $status_file = shift @ARGV; # open report for reading open my $rfh, '<', $report_file or die "open($report_file,<) failed: $!"; # tie status file to array tie( my @status, 'Tie::File', $status_file ) or die "Cannot tie $status_file: $!"; LINE: while ( my $line = <$rfh> ) { warn "(D) read: $line\n"; # skip empty lines next LINE if $line =~ m/^\s*$/; chomp $line; # split into fields my ( $field1, $field2, $date1, $date2 ) = split m/\t/, $line; # no action if "date2" is not "-"; read next line next LINE if $date2 ne '-'; # prepare a string to compare from first three fields my $to_save = join "\t", $field1, $field2, $date1; # write to status file if string has not been seen yet if ( ! first { $_ eq $to_save } @status ) { push @status, $to_save; } } close $rfh; __END__ Zusätzlicher Gedanke: Variante 1 ließe sich noch umgestalten, in dem man eine Prüfsumme von $to_save erstellt und diese in dem Hash %seen ablegt und den Vergleich dann über die Prüfsummen macht. Gerade wenn die Felder groß werden, könnte das ein Ansatz sein, um den Speicherbedarf geringer zu halten. edit: fehlende Sprungmarken im Code ergänzt Last edited: 2016-11-23 13:29:22 +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! |