Inhalt von zwei Dateien vergleichen
Fritzek
- perl
Hallo
Ich habe folgendes Problem:
Für einen PERL-Profi sicherlich ein Klacks, für mich der Mount Everest ;-)
Danke für Eure Hilfe
Fritzek
gudn tach Fritzek!
- 2 Dateien: datei_1 ist die zu durchsuchende Menge und datei_2 beinhaltet in jeder Zeile einen Suchbegriff, den ich in datei_1 finden möchte
- wenn ich eine Zeile in datei_1 gefunden habe, die einen Suchbegriff beinhaltet, möchte ich die Zeilennummer wissen
weisst du wie man dateien einliest und wie man einen string in einem anderen sucht?
anders gefragt: wie weit bist du denn schon?
prost
seth
gudn tach Fritzek!
- 2 Dateien: datei_1 ist die zu durchsuchende Menge und datei_2 beinhaltet in jeder Zeile einen Suchbegriff, den ich in datei_1 finden möchte
- wenn ich eine Zeile in datei_1 gefunden habe, die einen Suchbegriff beinhaltet, möchte ich die Zeilennummer wissen
weisst du wie man dateien einliest und wie man einen string in einem anderen sucht?
anders gefragt: wie weit bist du denn schon?prost
seth
ganz am anfang. in der theorie weiß ich, wie ich dateien öffne und in ein array auslese. dann beisst es sich aber schon aus. irgendwie muss ich dann durch das große array durchloopen und in jeder zeile das kleine array loopen. und dann hörts leider auf.
Fritzek
gudn tach!
in der theorie weiß ich, wie ich dateien öffne und in ein array auslese.
in der praxis auch?
also z.b. so:
sub loadFile{
my $infile=shift;
open(INFILE, "<".$infile) || die " file not found\n";
my @lines=<INFILE>;
close(INFILE);
return @lines;
}
my @file_content=loadFile('file.txt');
irgendwie muss ich dann durch das große array durchloopen und in jeder zeile das kleine array loopen.
ja, z.b. in etwa so
schleife ueber alle zeilen der zu durchsuchenden datei
schleiche ueber alle strings (nadeln), nach denen gesucht werden soll
suche nadel im zeile
falls gefunden: zeilennummernausgabe
schleifenende
schleifenende
suchen kannst du mit regulaeren ausdruecken (perldoc perlre).
so und jetzt faehrt gleich mein bus...
prost
seth
gudn tach!
in der theorie weiß ich, wie ich dateien öffne und in ein array auslese.
in der praxis auch?
also z.b. so:
sub loadFile{
my $infile=shift;
open(INFILE, "<".$infile) || die " file not found\n";
my @lines=<INFILE>;
close(INFILE);
return @lines;
}
my @file_content=loadFile('file.txt');
>
> > irgendwie muss ich dann durch das große array durchloopen und in jeder zeile das kleine array loopen.
>
> ja, z.b. in etwa so
> schleife ueber alle zeilen der zu durchsuchenden datei
> schleiche ueber alle strings (nadeln), nach denen gesucht werden soll
> suche nadel im zeile
> falls gefunden: zeilennummernausgabe
> schleifenende
> schleifenende
>
> suchen kannst du mit regulaeren ausdruecken (perldoc perlre).
>
> so und jetzt faehrt gleich mein bus...
>
> prost
> seth
Danke, seth.
so hatte ich mir das mit dem einlesen gedacht:
~~~perl
my $i = 0;
my $j = 0;
open(DATEI_1, "datei_1") || die "Datei nicht gefunden";
my @Zeilen_1 = <DATEI_1>;
close(DATEI_1);
open(DATEI_2, "datei_2") || die "Datei nicht gefunden";
my @Zeilen_2 = <DATEI_2>;
close(DATEI_2);
foreach $inhalt_1 (@Zeilen_1) {
++$i;
foreach $inhalt_2 (@Zeilen_2) {
++$j;
if ( $inhalt_1[$i] =~ /$inhalt_2[$j]/ ) {
print $i;
}
}
}
ich muss nicht mal nach RegExp suchen; sind ganze wörter. einzig die nummer der aktuellen zeile muss ich ausgeben. ich versuch das ganze als perl -e test.pl laufen zu lassen und es kommt nichts.
Danke, Fritzek
so hatte ich mir das mit dem einlesen gedacht:
my $i = 0;
my $j = 0;
open(DATEI_1, "datei_1") || die "Datei nicht gefunden";
In $! steht der wirkliche Grund, warum das öffnen scheitert.
open(DATEI_1, "datei_1") || die "Kann Datei nicht öffnen, weil: $!";
foreach $inhalt_1 (@Zeilen_1) {
++$i;
foreach $inhalt_2 (@Zeilen_2) {
++$j;
if ( $inhalt_1[$i] =~ /$inhalt_2[$j]/ ) {
Du brauchst den Index gar nicht zumal er falsch ist.
$inhalt_1 und $inhalt_2 enthalten die aktuelle Zeile.
Einfacher wäre es aber nicht erst die ganze Datei einzulesen, zumal das u.U. viel Speicher verbrät, du könntest so direkt die Zeilenummer mit $. ermitteln.
Also in etwa so:
[code lang=perl]#!/usr/bin/perl -w
use strict;
open(DATEI_1, "datei_1") || die "Kann Datei nicht öffnen, weil: $!";
my @suchen = <DATEI_1>;
close(DATEI_1);
open(DATEI_2, "datei_2") || die "Kann Datei nicht öffnen, weil: $!";
while my $zeile(<DATEI_2>)
{
foreach my $suche (@suchen)
{
# jedes Suchwort in der aktuellen Zeilen suchen
if ( $zeile =~ /$suche/ )
{
print "$suche Gefunden in Zeile: $.\n";
}
}
}
Struppi.
--
[Javascript ist toll](http://javascript.jstruebig.de/)
Tag Struppi.
Da RegExp ja nachgesagt wird, dass sie Performancekiller seien, wäre es mal interessant zu erfahren, ob ein Hash-Slice nicht eventuelle Performancegewinne bringen würde:
open(DATEI_1, "datei_1") || die "Kann Datei nicht öffnen, weil: $!";
my @suchen = <DATEI_1>;
close(DATEI_1);
~~~perl
my %gesucht;
@gesucht{@suchen} = ();
open(DATEI_2, "datei_2") || die "Kann Datei nicht öffnen, weil: $!";
while (<DATEI_2>) {
chomp($_};
if( exists $gesucht{$_} ) {
print "$_ gefunden in Zeile: $.\n";
}
}
Nur mal so in den Raum gestellt ...
Siechfred
Da RegExp ja nachgesagt wird, dass sie Performancekiller seien, wäre es mal interessant zu erfahren, ob ein Hash-Slice nicht eventuelle Performancegewinne bringen würde:
Ich glaub nicht, wenn ich das richtig verstanden habe, dass in jeder Zeile nur ein Wort steht. Aber trotzdem könnte man die Suche beschleunigen.
open(DATEI_1, "datei_1") || die "Kann Datei nicht öffnen, weil: $!";
my @suchen = <DATEI_1>;
close(DATEI_1);
>
my $suchmuster = join '|', map quotemeta, @suchen;
>
> open(DATEI\_2, "datei\_2") || die "Kann Datei nicht öffnen, weil: $!";
> while (<DATEI\_2>) {
> chomp($\_};
Das Newline dürfte hier nicht stören.
if( /$suchmuster/ )
{
...
}
Wobei hier dann noch ein wenig mehr gemacht werden muss um rauszufinden, welche Suchbegriffe gefunden wurden.
Das ganze läuft dann so ganz gut:
~~~perl
#!/usr/bin/perl -w
use strict;
my @suchen = qw(Datei Text die);
my $suchmuster = join '|', map quotemeta, @suchen;
while(<DATA>)
{
my $zeile = $_;
my @gefunden = ($zeile =~ /($suchmuster)/gi);
if(@gefunden)
{
foreach(@gefunden)
{
print "$_ Gefunden in Zeile: $.\n";
}
}
}
__DATA__
Ein kleiner Text anstatt einer Datei
zum probieren der suche nach mehreren
Begriffen in einer Datei die ganz viele Zeilen hat
Ich bin gespannt ob die suche auch funktioniert
Struppi.
Da RegExp ja nachgesagt wird, dass sie Performancekiller seien, wäre es mal interessant zu erfahren, ob ein Hash-Slice nicht eventuelle Performancegewinne bringen würde:
Ich glaub nicht, wenn ich das richtig verstanden habe, dass in jeder Zeile nur ein Wort steht.
Ich habe es gerade mal getestet, der Hash-Slice wäre um einiges schneller als der RegExp, wenn es um den direkten Vergleich zweier Zeilen geht (so hatte ich jedenfalls den OP verstanden). Wobei bei deinem Ansatz m.E. die Verwendung von index zu empfehlen wäre, die ist in der Tat fixer als ein RegExp.
Siechfred
Hallo Struppi, hallo Siechfred
danke an euch und seth
so hab ich es hinbekommen:
#!/usr/bin/perl -w
use strict;
open(DATEI_1, "dat1.txt") || die "Datei nicht geoeffnet, weil: $!";
my @suchen = <DATEI_1>;
close(DATEI_1);
open(DATEI_2, "dat2.txt") || die "Datei nicht geoeffnet, weil: $!";
while (<DATEI_2>)
{
my $zeile = $_;
foreach (@suchen)
{
my $suche = $_;
if ( index($zeile,$suche) >= 0 )
{
print "$suche gefunden in Zeile: $.\n";
}
}
}
und das ging in der Tat mit index schneller (dat1 und dat2 hatten jeweils ungefähr 3000 Zeilen; dat1 wie gesagt nur ein wort und dat2 bestand die zeile aus zeichen zwischen 256 und 384 bytes). wobei "schneller" sich im sekundenbereich bewegt.
und das ging in der Tat mit index schneller (dat1 und dat2 hatten jeweils ungefähr 3000 Zeilen; dat1 wie gesagt nur ein wort und dat2 bestand die zeile aus zeichen zwischen 256 und 384 bytes). wobei "schneller" sich im sekundenbereich bewegt.
Ja, die Suche mit index ist mehr als dreimal so schnell.
Struppi.
und das ging in der Tat mit index schneller (dat1 und dat2 hatten jeweils ungefähr 3000 Zeilen; dat1 wie gesagt nur ein wort und dat2 bestand die zeile aus zeichen zwischen 256 und 384 bytes). wobei "schneller" sich im sekundenbereich bewegt.
Ja, die Suche mit index ist mehr als dreimal so schnell.
Struppi.
letzte frage: nach dem test unter linux mit perl 5.6 hab ich es aufs zielsystem sun mit perl 5.005_03 kopiert und da geht gar nichts (weder fehler meldungen noch irgendetwas von print). woran kann das liegen?
danke, Fritzek
letzte frage: nach dem test unter linux mit perl 5.6 hab ich es aufs zielsystem sun mit perl 5.005_03 kopiert und da geht gar nichts (weder fehler meldungen noch irgendetwas von print). woran kann das liegen?
Du führst das Skript auf der Konsole aus und bekommmst keine Meldung?
Struppi.
letzte frage: nach dem test unter linux mit perl 5.6 hab ich es aufs zielsystem sun mit perl 5.005_03 kopiert und da geht gar nichts (weder fehler meldungen noch irgendetwas von print). woran kann das liegen?
Du führst das Skript auf der Konsole aus und bekommmst keine Meldung?
Struppi.
ja, aber wie ich eben schrieb arbeitet er, aber das index irgendwie nicht (prints zum debuggen haben meldungen gebracht).
ja, aber wie ich eben schrieb arbeitet er, aber das index irgendwie nicht (prints zum debuggen haben meldungen gebracht).
Funktionier das:
#!/usr/bin/perl -w
use strict;
my @suchen = qw(Datei Text die);
while( my $zeile = <DATA>)
{
foreach my $suche (@suchen)
{
if ( index($zeile,$suche) > -1 )
{
print "$suche($.)\n";
}
}
}
__DATA__
Ein kleiner Text anstatt einer Datei
zum probieren der suche nach mehreren
Begriffen in einer Datei die ganz viele Zeilen hat
Ich bin gespannt ob die suche auch funktioniert
Struppi.
Funktionier das:
#!/usr/bin/perl -w
use strict;
my @suchen = qw(Datei Text die);
while( my $zeile = <DATA>)
{
foreach my $suche (@suchen)
{
if ( index($zeile,$suche) > -1 )
{
print "$suche($.)\n";
}
}
}DATA
Ein kleiner Text anstatt einer Datei
zum probieren der suche nach mehreren
Begriffen in einer Datei die ganz viele Zeilen hat
Ich bin gespannt ob die suche auch funktioniert
>
> Struppi.
Nop. alle zeilen aus dat2 liefern -1 zurück. ich hab aber ganz bewusst in dat1 begriffe aus dat2 reingeschrieben. die müssen also definitiv vorhanden sein. wie geht index eigentlich mit gross-klein-schreibung um? (in meinem fall nicht relevant, da ich die begriffe so geschrieben habe wie in dat2 zu finden).
Nop. alle zeilen aus dat2 liefern -1 zurück. ich hab aber ganz bewusst in dat1 begriffe aus dat2 reingeschrieben. die müssen also definitiv vorhanden sein. wie geht index eigentlich mit gross-klein-schreibung um? (in meinem fall nicht relevant, da ich die begriffe so geschrieben habe wie in dat2 zu finden).
index ist case sensitive, wenn das nicht geht ist vielleicht was an deiner Perl Version kaputt. Gibt's keine neuere?
Struppi.
index ist case sensitive, wenn das nicht geht ist vielleicht was an deiner Perl Version kaputt. Gibt's keine neuere?
Struppi.
leider nein, jedenfalls darf ich keine neuere installieren :(
macht aber nichts, da es eh nur um von-fall-zu-fall sachen geht. da kann man sich die dateien zur not auf eine andere maschine kopieren und lässt es dort laufen. werd noch ein bisschen rumtüfteln. vielleicht find ich noch was. danke einstweilen.
und das ging in der Tat mit index schneller (dat1 und dat2 hatten jeweils ungefähr 3000 Zeilen; dat1 wie gesagt nur ein wort und dat2 bestand die zeile aus zeichen zwischen 256 und 384 bytes). wobei "schneller" sich im sekundenbereich bewegt.
Ja, die Suche mit index ist mehr als dreimal so schnell.
Struppi.
letzte frage: nach dem test unter linux mit perl 5.6 hab ich es aufs zielsystem sun mit perl 5.005_03 kopiert und da geht gar nichts (weder fehler meldungen noch irgendetwas von print). woran kann das liegen?
danke, Fritzek
Hmm... er macht schon noch was aber das index funktioniert nicht so richtig.
Hallo,
letzte frage: nach dem test unter linux mit perl 5.6 hab ich es aufs zielsystem sun mit perl 5.005_03 kopiert und da geht gar nichts (weder fehler meldungen noch irgendetwas von print). woran kann das liegen?
Vielleicht liegts auch einfach nur daran, dass die Elemente von @suchen noch die Zeilenumbrüche beinhalten und Dein erster Test darum gut ging, weil die Suchworte in der zu überprüfenden Datei zufällig am Ende der Zeilen standen.
Grüße
Klaus
Vielleicht liegts auch einfach nur daran, dass die Elemente von @suchen noch die Zeilenumbrüche beinhalten und Dein erster Test darum gut ging, weil die Suchworte in der zu überprüfenden Datei zufällig am Ende der Zeilen standen.
Grüße
Klaus
danke, Klaus, für den Hinweis. Hab ich untersucht und kam zu folgenden Ergebnissen:
1. alle Elemente von @suchen stehen allein in einer Zeile
2. habe die Datei mit und ohne CRLF (also unix2dos und dos2unix) ausprobiert
3. keines der Suchworte war in der zu überprüfenden Datei am Ende der Zeile
Bin ratlos, aber nicht hilflos ;-)
Gruß, Fritzek
Tag Fritzek.
Vielleicht liegts auch einfach nur daran, dass die Elemente von @suchen noch die Zeilenumbrüche beinhalten und Dein erster Test darum gut ging, weil die Suchworte in der zu überprüfenden Datei zufällig am Ende der Zeilen standen.
Hab ich untersucht und kam zu folgenden Ergebnissen:
- alle Elemente von @suchen stehen allein in einer Zeile
Damit würde Klaus' Vermutung aber zutreffen, dass in @suchen alle Worte inklusive Zeilenumbruch stehen.
- habe die Datei mit und ohne CRLF (also unix2dos und dos2unix) ausprobiert
Damit hast du den Zeilenumbruch nicht entfernt, sondern lediglich zwischen LF und CRLF hin- und herkonvertiert.
- keines der Suchworte war in der zu überprüfenden Datei am Ende der Zeile
Damit sollte das Problem gefunden sein und ein chomp(@suchen) Abhilfe schaffen.
Siechfred
Hallo Siechfred
danke, das war der entscheidende hinweis. jetzt sieht das programm wie folgt aus und funktioniert in jeder umgebung:
#!/usr/bin/perl -w
use strict;
open(DATEI_1, "dat1.txt") || die "Datei nicht geoeffnet, weil: $!";
my @suchen = <DATEI_1>;
chomp(@suchen);
close(DATEI_1);
open(DATEI_2, "dat2.txt") || die "Datei nicht geoeffnet, weil: $!";
while (<DATEI_2>)
{
my $zeile = $_;
foreach (@suchen)
{
my $suche = $_;
if ( index($zeile,$suche) > -1 )
{
print "$suche gefunden in Zeile: $.\n";
}
}
}
Dank an alle für ihre Hilfe.
my @suchen = <DATEI_1>;
chomp(@suchen);
Damit enfernst du aber nur das Newline von einer Zeile.
Du meinst wahrscheinlich:
chomp( my @suchen = <DATEI_1>);
while (<DATEI_2>)
{
my $zeile = $_;
wie schon gesagt das kannst du kürzer Schreiben:
while (my $zeile = <DATEI_2>)
foreach (@suchen)
{
my $suche = $_;
und hier auch:
foreach my $suche( @suchen)
Struppi.
my @suchen = <DATEI_1>;
chomp(@suchen);Damit enfernst du aber nur das Newline von einer Zeile.
Du meinst wahrscheinlich:
chomp( my @suchen = <DATEI_1>);while (<DATEI_2>)
{
my $zeile = $_;wie schon gesagt das kannst du kürzer Schreiben:
while (my $zeile = <DATEI_2>)foreach (@suchen)
{
my $suche = $_;und hier auch:
foreach my $suche( @suchen)Struppi.
Danke, Struppi, für die Hinweise. Werd es sofort erledigen und dann mal gegen was ganz großes laufen lassen: 18 Mio Zeilen und drei Suchbegriffe. Werd euch berichten, wie lange es gedauert hat.
Fritz, the Cat
Hi, ich noch mal
das mit dem "groß" war nich so gut: Value too large for defined data type
die datei is 5gig groß. habt ihr ne idee, wie man die größenordnung handhaben kann?
Fritz, the "kiddy" :(
das mit dem "groß" war nich so gut: Value too large for defined data type
die datei is 5gig groß. habt ihr ne idee, wie man die größenordnung handhaben kann?
Die Frage ist was du genau machst?
Exakt 1:1 das Skript was wir hier gesehen haben?
Struppi.
das mit dem "groß" war nich so gut: Value too large for defined data type
die datei is 5gig groß. habt ihr ne idee, wie man die größenordnung handhaben kann?Die Frage ist was du genau machst?
Exakt 1:1 das Skript was wir hier gesehen haben?Struppi.
Ja, ergänzt um deine letzten bemerkungen. ansonsten ist nichts anders außer die namen der dateien.
Fritzek
Ja, ergänzt um deine letzten bemerkungen. ansonsten ist nichts anders außer die namen der dateien.
Kann es sein, dass in dieser Datei die Zeilenumbrüche nicht zum System passen und Perl daher versucht die Datei in einem Rutsch einzulesen?
Struppi.
Ja, ergänzt um deine letzten bemerkungen. ansonsten ist nichts anders außer die namen der dateien.
Kann es sein, dass in dieser Datei die Zeilenumbrüche nicht zum System passen und Perl daher versucht die Datei in einem Rutsch einzulesen?
Struppi.
wäre ungewöhnlich. die datei wird als spool datei aus der datenbank erzeugt. und das auf der maschine, auf der ich das script laufen lassen will. und das ist solaris 8.
Fritzek
wäre ungewöhnlich. die datei wird als spool datei aus der datenbank erzeugt. und das auf der maschine, auf der ich das script laufen lassen will. und das ist solaris 8.
Naja, du kannst es feststellen, in dem du prüfst ob überhaupt das Zeilenweise einlesen der Datei klappt (was es sollte), also sowas:
open FH, "datei";
while(<FH>)
{
print;
}
Struppi.
Naja, du kannst es feststellen, in dem du prüfst ob überhaupt das Zeilenweise einlesen der Datei klappt (was es sollte), also sowas:
Hi Struppi
gleiche Meldung: Value too large for defined data type
Naja, du kannst es feststellen, in dem du prüfst ob überhaupt das Zeilenweise einlesen der Datei klappt (was es sollte), also sowas:
Hi Struppi
gleiche Meldung: Value too large for defined data type
Sieht für mich so aus als ob Perl versucht die ganze Datei aufeinmal einzulesen.
Struppi.
Sieht für mich so aus als ob Perl versucht die ganze Datei aufeinmal einzulesen.
Struppi.
denk ich auch. hab mir jetzt so beholfen, dass ich einen Teil des files mit grep abgesplittet habe und auf dem verbleibenden Teil das Script hab laufen lassen. das file war gut ein gig groß und das script hat funktioniert. wundert mich aber trotzdem: die maschine hat 32 gig ram und 12 proz, sollte daher kein problem sein. hat perl da ein limit, weil er doch was von defined data type schreibt.
Fritzek
Tag Struppi.
Damit enfernst du aber nur das Newline von einer Zeile.
Aus der Doku zu chomp:
"If you chomp a list, each element is chomped, and the total number of characters removed is returned."
Oder meintest du was anderes?
Siechfred
Damit enfernst du aber nur das Newline von einer Zeile.
Aus der Doku zu chomp:
"If you chomp a list, each element is chomped, and the total number of characters removed is returned."
Oder meintest du was anderes?
Nö, hast recht
ich hatte nur kurz getestet und offensichtlich nicht genau hingeschaut.
Struppi.
while (<DATEI_2>)
{
my $zeile = $_;
foreach (@suchen)
{
my $suche = $_;
if ( index($zeile,$suche) >= 0 )
{
print "$suche gefunden in Zeile: $.\n";
}
}
}
[/code]
Hier noch zwei kleine Verbesserungen:
while (my $zeile = <DATEI_2>)
{
foreach my $suche (@suchen)
{
if ( index($zeile,$suche) >= 0 )
{
print "$suche gefunden in Zeile: $.\n";
}
}
}
Struppi.