banales problem scheiter an Einfachslosigkeit :)

belubaba

belubaba

Tripel-As
Ich habe ein relativ banales Problem das sich wie folgt gestaltet:

Code:
Datei1.txt

ID - TAB - freitext TAB ....

89            igendeinText      ....
2             mit~belib@igen    ....
857         zeichen    ....

Datei2.txt

ID - KOMMA - neuerText KOMMA

76,weitererTEXT, ....
89,weitererTAXT, ....
857,weitererTUXT, ....
3,weitererTIXT, ....

Der Freitext in Datei1.txt soll bei passender ID durch neuerText in Datei2.txt erstetzt werden.

Das ist warscheinlich ein Einzeiler wenn man awk kann aber mit Unix Shell Skript mag mir kein Ansatz einfallen bei dem ich nicht stundenlang rumprobieren müsste.

Hat jemand eine Idee?

belubaba
 
So richtig banal ist das nicht (für einen Einzeiler), da du ja über mehrere Filehandles iterieren musst.

Hier mal ein Krüppel in perl:
Code:
$ cat source 
89            igendeinText      ....
2             mit~belib@igen    ....
857         zeichen    ....
$ cat dest
76,weitererTEXT, ....
89,weitererTAXT, ....
857,weitererTUXT, ....
3,weitererTIXT, ....
$ perl -anF'\s+' -e '$src{$F[0]}=$F[1];last if eof;END{while(<>){@a=split",";s/\Q$a[1]\E/$src{$a[0]}/ if exists$src{$a[0]};print;}}' source dest
76,weitererTEXT, ....
89,igendeinText, ....
857,zeichen, ....
3,weitererTIXT, ....

Hier mal perltidied und mit den cli-Switches explizit eingebaut:
Code:
while ($_ = <>) {
    @F = split /\s+/, $_;
    $src{$F[0]} = $F[1];
    last if eof;
}
END {
    while ($_ = <>) {
        @a = split ",", $_;
        s/\Q$a[1]\E/$src{$a[0]}/ if exists $src{$a[0]};
        print $_;
    }
}
Hilft dir aber ohne perl-Kenntnisse wahrscheinlich trotzdem nicht weiter, deswegen ein paar Denkanstöße:
Da du ja nicht für jede ID der 2. Datei komplett über die erste Iterieren willst, nur um alle IDs zu vergleichen, bietet es sich natürlich an, die Daten der ersten Datei in eine Datenstruktur zu packen. (Ich habs in ein Hash (%src) gepackt.) Dann kannst du während des über die zweite Datei Iterierens schauen, ob du eine Identische ID in deiner Datenstruktur hast und in diesem Fall halt das Textfeld (das 2.) "austauschen". Das ganze würde ich dann in eine 3. Datei schreiben und danach Datei3 einfach in Datei2 umbenennen.
Aber vielleicht gehts ja einfacher. Warte mal besser weitere Posts ab.
Du könntest hier sogar mit bash arbeiten, da die Arrays in der bash ja eigentlich auch nur hashes mit Integer-Indices sind (was auf die ID ja immer zutreffen dürfte...), von daher.
 
Hölzern (unter geflissentlicher Vernachlässigung der von Gott_in_schwarz gegebenen Hinweise :D) :

Code:
$ cat Datei1
89      igendeinText      ....
2       mit~belib@igen    ....
857     zeichen    ....

$cat Datei2
76,weitererTEXT, ....
89,weitererTAXT, ....
857,weitererTUXT, ....
3,weitererTIXT, ...

$cat test.sh
while read zeile; do 
    ID="$(echo "$zeile" | cut -d\, -f1)"
    TXT1="$(echo "$zeile" | cut -d\, -f2)"
    TXT2="$(grep $ID $1|cut -f2)"
    test "$TXT2" && echo "${zeile/$TXT1/$TXT2}" || echo "$zeile"  
done < $2

./test.sh Datei1  Datei2
76,weitererTEXT, ....
89,igendeinText ...., ....
857,zeichen ...., ....
3,weitererTIXT, ...

Wie das mit bash-arrays schöner geht, soll jemand anders rauspuzzeln ...
 
Zuletzt bearbeitet:
Erstmal danke für beide Vorschläge. Ich werde beide ausprobieren.
Meine erste Datei wird sowieso von einem Pearl Programm erzeugt.
Da liegt es nahe diese gleich in der richtigen Form zu erzeugen.

Vermutlich werde ich aber Lösung zwei nehmen, hauptsächlich weil ich diese verstehe,
und weil mir gerade das Brett vor dem Kopf klar wurde als ich das cut gesehen habe :)

Gespannt bin ich auf die Laufzeit auf meinem klein dimensionierten Webserver. Da beide Dateien über 500 Einträge enthalten und anwachsen :).

belubaba
 
Ne, Array ist natürlich nicht notwendig, was du gemacht hast ist dann halt für jede ID komplett Datei 1 nochmal öffnen. Wenn das performance-mäßig klargeht, ist das sicherlich eine gute (weil gut verständliche) Lösung.

mir schrieb:
Da du ja nicht für jede ID der 2. Datei komplett über die erste Iterieren willst, nur um alle IDs zu vergleichen, bietet es sich natürlich an, die Daten der ersten Datei in eine Datenstruktur zu packen.

Vielleicht den grep-Ausdruck noch zu "^$ID" ändern, damit die ID auch wirklich am Anfang steht. Dann ist das doch eine feine Lösung :)
Und @ mein perl-Einzeiler: weil mein vim aus tabs Leerzeichen macht hab ich einfach mit der regex '\s+' gesplittet, das könntest du dann einfach in '\t' umändern (wenns denn richtige Tabs in der Datei sind).
 
Zurück
Oben