[Perl]Zwei Dateien zusammenfügen


chill0r55555

Mitglied
Hallo,
ich bastle gerade an einem Skript mit dem ich Dateien zusammenfügen kann.
Soll wie folgt funktionieren:

Datei.txt
Code:
111[TABULATOR]Markus
222[TABULATOR]Micha
333[TABULATOR]Peter
444[TABULATOR]Hans[TABULATOR]Bemerkung
555[TABULATOR]Lisa
Preset.txt
Code:
999[TABULATOR]Hans[TABULATOR]Bemerkung
888[TABULATOR]Klaus[TABULATOR]blabla
Das Skript liest jetzt beide Dateien ein, dann geht er die Preset.txt durch.
Dort nimmt er als Suchbegriff den Namen der Personen. Nun wird nach dem Namen
von Preset.txt in der Datei "Datei.txt" gesucht. Sollte ein Treffer vorhanden sein,
dann wird die Komplette Zeile der Datei "Datei.txt" durch die entsprechende Zeile
in "Preset.txt" ersetzt. Soweit funktioniert mein Skript auch ganz gut, nur habe ich
das Problem das ich es nicht hinbekomme, wenn ein Eintrag aus Preset.txt nicht in Datei.txt
gefunden wird dieser dann auch hinzugefügt werden soll. Zudem ist meine Idee mit den Zwei
Schleifen nicht die Beste, da die Ausgabe doppelt ist:

Ausgabe:

Code:
111     Markus
222     Micha
333     Peter
#Kommentar
999     Hans    Bemerkung
555     Lisa
111     Markus
222     Micha
333     Peter
#Kommentar
444     Hans    Bemerkung
555     Lisa

Das ist mein Skript:

Perl:
#!/usr/bin/perl -w


use strict;
use Tie::File;

my $datei = 'Datei.txt';
my $datei2 = 'Preset.txt';
my @output=();
my $count=0;
my @preset=();

# Datei einlesen
tie my @array,'Tie::File', $datei or die $!;

# Preset-Datei einlesen
open (my $file, '<', $datei2) or die $!;
while(<$file>)
{
        chomp;
        # Leerzeilen und Kommentare im Presetfile ignorieren
        if (m/^\s*$/ || m/^#.*/) { next; }
        @{$preset[$count++]} = split("\t", $_);
  }
  close $file;


for(my $i=0; $i <= $#preset; ++$i)
{
  for(my $j=0; $j <= $#array; ++$j)
  {
    if ($hosts[$j] =~ /$preset[$i]->[1]/){
        push(@output,$preset[$i]->[0]."\t".$preset[$i]->[1]."\t".$preset[$i]->[2]);
    }
    else{
        push(@output,$array[$j]);
    }
  }
}

untie @array;

foreach my $eintrag(@output){
    print $eintrag."\n";
}

Ich hoffe ich hab mich nicht zu unverständlich ausgedrückt.
MfG
 

renee

Erfahrenes Mitglied
Ich würde die Daten.txt mit Tie::File an ein Array binden. Danach durch die Presse.txt zeilenweise gehen und dann überprüfen, ob in Daten.txt ein Eintrag vorhanden ist:

Code:
#!/usr/bin/perl

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

my $daten = 'Daten.txt';
my $presse = 'Presse.txt';

# binde Daten.txt mit Tie::File an ein Array
tie my @lines, 'Tie::File', $daten or die $!;

# oeffne Presse.txt zum lesen
# mehr zu open unter http://reneeb-perlblog.blogspot.com/2009/09/verschiedenes-zu-open.html
open my $fh, '<', $presse or die $!;

# gehe zeilenweise durch Datei
while( my $line = <$fh> ) {
    
    # Entferne Zeilenumbruch
    chomp $line;
    
    # Hole vergleichsname aus Zeile
    my (undef,$vorname) = split /\t/, $line, 2;
        
    # Pruefe Zeilen in Daten.txt
    my $found = 0;
    for my $daten_zeile ( @lines ) {
        if( $daten_zeile =~ /^\d+\t$vorname$/ ) {
            $found = 1;
            $daten_zeile = $line;
            warn $found;
            last;
        }
    }

    # wenn nicht gefunden haenge Zeile an Daten.txt
    push @lines, $line if !$found;
}

# löse Bindung
untie @lines;
 

chill0r55555

Mitglied
Ich danke dir für deine Hilfe und Mühe. Ich habe gerade dein Skript getestet und es funktioniert.
Nur hab ich noch ein kleines Problem. Undzwar ist es so, dass wenn die Bemerkung von Presse.txt unterschiedlich ist zu dem in Daten.txt er mir die Zeile als neuen Datensatz anhängt.

Hier mal ein Beispiel:
Daten.txt
Code:
444[TAB]Hans[TAB]Bemerkung
Presse.txt
Code:
999[TAB]Hans[TAB]Bemerkung2
Nach denm Skript aufruf sieht die Daten.txt so aus:
Code:
444[TAB]Hans[TAB]Bemerkung
999[TAB]Hans[TAB]Bemerkung2
Das ganze verstehe ich nicht so wirklich, da der regex ja nach Ziffern gefolgt von einem Tabulator und dann dem Namen sucht. Somit müsste dann ja einfach aus Bemerkung Bemerkung2 werden.


MfG
 

renee

Erfahrenes Mitglied
Mach mal aus

Perl:
my (undef,$vorname) = split /\t/, $line, 2;
einfach
Perl:
my (undef,$vorname) = split /\t/, $line;
Und aus

Perl:
if( $daten_zeile =~ /^\d+\t$vorname$/ ) {
das hier:
Perl:
if( $daten_zeile =~ /^\d+\t$vorname(\t|$)/ ) {
 

Neue Beiträge