Schrift
[thread]9153[/thread]

Zwei dateien vergleichen

Leser: 2


<< >> 7 Einträge, 1 Seite
Gast Gast
 2007-07-04 14:05
#78175 #78175
Hallo zusammen,

ich möchte mit Perl zwei Textdateien vergleichen. Die Einträge in den Textdateien haben folg. Form:

jmd. hat ein Haus
jmd. hat ein Auto

Es soll festgestellt werden, ob die Einträge aus Datei1 auch in der Datei2 enthalten sind. Dabei soll das Programm in der Datei1 für jeden Eintrag das großgeschriebene Wort extrahieren und nach allen Einträgen, die dieses Wort enthalten, in der Datei2 suchen, also:

jmd. hat ein Haus  --> Haus --> in Datei2 suchen --> nicht gefunden --> den ganzen Ausdruck in die Datei2 schreiben --> ok

jmd. hat ein Auto --> Auto --> in Datei2 suchen --> gefunden --> Ausdruck ist in der Liste --> ok

Kann mir jemand einen Tip geben, wie ich das implementiere?

Danke und Gruß

Mary
renee
 2007-07-04 14:21
#78176 #78176
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Dafür kann man ganz gut CPAN:Tie::File verwenden. Wenn die Datei2.txt etwas größer wird, sollte man die if-Abfrage mit dem grep durch etwas performanteres ersetzen, für kleinere Dateien ist das aber durchaus sehr gut geeignet...

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
#!/usr/bin/perl

use strict;
use warnings;
use Tie::File;

my $file_one = 'Datei1.txt';
my $file_two = 'Datei2.txt';

open my $fh, '<', $file_one or die $!;
tie my @lines, 'Tie::File', $file_two or die $!;

while( my $line = <$fh> ){
    chomp $line;
    my @words = $line =~ /\b([A-Z].*?)\b/g;
    for my $word ( @words ){
        unless( grep{ $_ =~ /\Q$word\E/ }@lines ){
            push @lines, $line;
        }
    }
}

untie @lines;

close $fh;
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
bloonix
 2007-07-04 15:24
#78177 #78177
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
Ein wenig Hintergrundwissen wäre natürlich nicht schlecht. Handelt es sich
beispielsweise bei Datei2 um eine datenbankähnliche Datei die mehrere
Gigabyte groß sein kann und die mit neuen nicht existierenden Datensätzen
aus Datei1 gefüttert werden soll oder handelt es sich einfach um ein "diff"
von zwei Textdateien?\n\n

<!--EDIT|opi|1183548424-->
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
Mary
 2007-07-04 15:50
#78178 #78178
User since
2006-06-25
17 Artikel
BenutzerIn
[default_avatar]
Ja, genau, es ist eine datenbankähnliche Datei, die mit neuen Einträgen vervollständigt werden soll. Die Lösung von renee funktioniert ganz gut, ist aber für größere Dateien wohl weniger geeignet. Außerdem sollen neue Abgleichkriterien dazu kommen, z.B. neben dem großgeschriebenen Wort soll auch das Verb analysiert werden. Beispiel:

Datei2 enthält den Eintrag "jmd. baut ein Haus", aber nicht "jmd. hat ein Haus", also soll er aus Datei1 hinzugefügt werden.
renee
 2007-07-04 16:11
#78179 #78179
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Das wird dann ein wenig komplizierter, weil Du erst das Verb herausfinden musst...

Ansonsten funktioniert meine Lösung auch mit größeren Dateien. Nur wird es noch performanter, wenn es so abgeändert wird (ungetestet):
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
#!/usr/bin/perl

use strict;
use warnings;
use Tie::File;

my $file_one = 'Datei1.txt';
my $file_two = 'Datei2.txt';

open my $fh, '<', $file_one or die $!;
tie my @lines, 'Tie::File', $file_two or die $!;

while( my $line = <$fh> ){
    chomp $line;
    my @words = $line =~ /\b([A-Z].*?)\b/g;
    for my $word ( @words ){
        unless( check( $word, @lines ) ){
            push @lines, $line;
        }
    }
}

untie @lines;

close $fh;

sub check{
    my ($value) = shift;
    for my $line ( @_){
         return 1 if $line =~ /\Q$value\E/;
    }
    return;
}
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
Mary
 2007-07-04 17:29
#78180 #78180
User since
2006-06-25
17 Artikel
BenutzerIn
[default_avatar]
Danke, das ist eine gute Lösung!

Hast Du auch eine Idee, wie ich andere Kriterien miteinbeziehen könnte, z.B. das Verb?
Mary
 2007-07-05 13:44
#78181 #78181
User since
2006-06-25
17 Artikel
BenutzerIn
[default_avatar]
Ich habe versucht, die Lösung mit dem Verb zu implementieren, aber es funktioniert nicht richtig. Kann mir jemand sagen, was hier nicht stimmt?

Code: (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
my $file_one = 'Datei1.txt';
my $file_two = 'Datei2.txt';

open my $fh, '<', $file_one or die $!;
tie my @lines, 'Tie::File', $file_two or die $!;

while( my $line = <$fh> ){
   chomp $line;
   my @verbs = $line =~ /\b([a-z.\/-]+)\b([a-z]*?[t])\b/g;
   my @words = $line =~ /\b([A-Z].*?)\b/g;
   for my $verb (@verbs){
       if ( checkverb( $verb, @lines ) ){
           for my $word ( @words ){
               unless( check( $word, @lines ) ){
                   push @lines, $line;
               }
           }
       }
       else{
           push @lines, $line;
       }
   }
}

untie @lines;

close $fh;

sub checkverb{
my ($value) = shift;
   for my $line ( @_){
        return 1 if $line =~ /\Q$value\E/;
   }
   return;
}

sub check{
   my ($value) = shift;
   for my $line ( @_){
        return 1 if $line =~ /\Q$value\E/;
   }
   return;
}
<< >> 7 Einträge, 1 Seite



View all threads created 2007-07-04 14:05.