93578
Goto Top

2 grosse txt-Dateien zeilenweise vergleichen und Zeilen in der Datei1 ersetzen ohne Duplikate zu loeschen

Hallo an alle,

ich habe folgendes Problem:

Es existieren 2 txt-Dateien, die so aussehen:

1)
xxxx
xxxx
xxxx
xxxx
yyyy
yyyy
yyyy
zzzz
zzzz
zzzz
(insgesamt 102.600.000 Zeilen)

2)
xxxx:abcd
yyyy:1234
zzzz:12ab
(insgesamt 50.000.000 Zeilen)

Nun will ich die beiden Dateien zeilenweise vergleichen und die Zeilen in der Datei 1, die mit Zeilen der Datei 2 identisch sind (xxxx, yyyy, zzzz), so ersetzen:

abcd
abcd
abcd
abcd
1234
1234
1234
12ab
12ab
12ab

Alle Duplikate in der Datei 1 müssen bleiben.

PS: Die Datein sind nicht sortiert! Falls es ohne Sortierung nicht geht oder zu lange dauern soll, kann ich sie natürlich sortieren.

PS2: Falls es einfacher ist auch so eine Lösung ist möglich: die gleiche Zeilen in der Datei 1 durch komplette Zeilen aus der Datei 2 ersetzen:

xxxx:abcd
xxxx:abcd
xxxx:abcd
xxxx:abcd
yyyy:1234
yyyy:1234
yyyy:1234
zzzz:12ab
zzzz:12ab
zzzz:12ab


Kann mir jemand helfen?

Content-Key: 354886

Url: https://administrator.de/contentid/354886

Ausgedruckt am: 29.03.2024 um 01:03 Uhr

Mitglied: Lochkartenstanzer
Lochkartenstanzer 15.11.2017 aktualisiert um 09:11:04 Uhr
Goto Top
Moin,

Hier ein Einzeiler für die bash:

cp file1.txt ziel.txt ; cat file2.txt | sed -e "s/:/\$:/1" | xargs -l1 -I XXXX echo "s:\^XXXX:1" | xargs -l1 -I XXXX sed -e "XXXX" -i ziel.txt

lks

PS: Das ist eine der vielen tausend Lösungsmöglichkeiten. face-smile
Mitglied: 93578
93578 15.11.2017 aktualisiert um 09:28:56 Uhr
Goto Top
Es klappt nicht:

ziel.txt:

xxxx
xxxx
xxxx
xxxx
1234
yyyy
yyyy
zzzz
zzzz
zzzz

Trotzdem, danke!
Mitglied: Lochkartenstanzer
Lösung Lochkartenstanzer 15.11.2017 aktualisiert um 09:52:24 Uhr
Goto Top
Zitat von @93578:

Es klappt nicht:

Dann haddu was falsch gemacht, bei mir sieht ziel.txt so aus:
lks@nana:~/tmp$ cat ziel.txt
abcd
abcd
abcd
abcd
1234
1234
1234
12ab
12ab
12ab

file1.txt:
xxxx
xxxx
xxxx
xxxx
yyyy
yyyy
yyyy
zzzz
zzzz
zzzz

file2.txt
xxxx:abcd
yyyy:1234
zzzz:12ab

lks
Mitglied: 93578
93578 15.11.2017 um 09:54:46 Uhr
Goto Top
Ja, Du hast Recht. UTF-8 vrgessen... face-sad

Vielen Dank!
Mitglied: 93578
93578 15.11.2017 aktualisiert um 09:59:29 Uhr
Goto Top
XXXX - stehen im Script für 4 Zeichen nach dem Doppelpunkt oder? Wie kann man vorgehen, falls es nach dem Doppelpunkt eine verschiedene Zeichenanzahl (0-99) ist?
Mitglied: Lochkartenstanzer
Lochkartenstanzer 15.11.2017 aktualisiert um 10:20:47 Uhr
Goto Top
Hier nochmal: der "große, ausführliche" Einzeiler inklusive Ausgaben:

lks@nana:~/tmp$ echo -e "\nfile1.txt:\n==========" ;  cat file1.txt ; echo -e "\nfile2.txt:\n==========" ; cat file2.txt ; cp file1.txt ziel.txt ; cat file2.txt | sed -e "s/:/\$:/1" | xargs -l1 -I Hampelmann1 echo "s:\^Hampelmann1:1" | xargs -l1 -I Hampelmann2 sed -e "Hampelmann2" -i ziel.txt ; echo -e "\nziel.txt:\n========" ; cat ziel.txt  

file1.txt:
==========
xxxx
xxxx
xxxx
xxxx
yyyy
yyyy
yyyy
zzzz
zzzz
zzzz

file2.txt:
==========
xxxx:abcd
yyyy:1234
zzzz:12ab

ziel.txt:
========
abcd
abcd
abcd
abcd
1234
1234
1234
12ab
12ab
12ab

lks

edit: XXXX durch Hampelmann ersetzt. face-smile
Mitglied: Lochkartenstanzer
Lösung Lochkartenstanzer 15.11.2017 um 10:01:28 Uhr
Goto Top
Zitat von @93578:

XXXX - stehen im Script für 4 Zeichen und wie kann man bei einer verschiedenen Zeichenanzahl (0-99) nach dem Doppelpunkt vorgehen?

nein. XXX ist der Parameter der "-I"-Option von xargs. damit wird dann in dem argument von xargs der parameter durch die zeile die xrags eingelesen hat ersetzt.

da könnte genausogut "Hampelmann" stehen.

lks
Mitglied: 93578
93578 15.11.2017 um 10:03:04 Uhr
Goto Top
Ok. Danke es funktioniert auch bei diversen Zeichnanzahl.

Vielen Dank! face-wink
Mitglied: 134464
134464 15.11.2017 aktualisiert um 10:06:54 Uhr
Goto Top
Das funktioniert aber nur solange er Sonderzeichen ($^.*\+() usw.) in seiner 2ten Datei mit Backslash escaped, denn sed arbeitet ja bekanntlich mit Regular Expressions in den Substitutions, du müsstest also noch ein sed "escaping" in die Pipeline dazwischen schieben.
Mitglied: Lochkartenstanzer
Lochkartenstanzer 15.11.2017 aktualisiert um 10:18:18 Uhr
Goto Top
Zitat von @134464:

Das funktioniert aber nur solange er Sonderzeichen ($^.*\+() usw.) in seiner 2ten Datei mit Backslash escaped, denn sed arbeitet ja bekanntlich mit Regular Expressions in den Substitutions, du müsstest also noch ein sed "escaping" in die Pipeline dazwischen schieben.

Schon klar. Das war ja auch nur ein Quick'n-Dirty-Einzeiler für die oben spezifizierten Daten zum einmaligen Gebrauch zum anschließenden Entsorgen. face-smile

Für Recyclingzwecke zum regelmäßigen Gebrauch muß dann daraus eine schönes Skript mit diversen Behandlungen von Sonderfällen gebastelt werden.

lks
Mitglied: 134464
134464 15.11.2017 aktualisiert um 10:15:40 Uhr
Goto Top
Wollte es nur erwähnen, nicht daß er nachher verwundert ist das bspw. ein
GG.F in Datei2
ein
GGHF in Datei1
ersetzt. face-smile
Mitglied: 93578
93578 15.11.2017 aktualisiert um 10:25:11 Uhr
Goto Top
/mnt/c/Users/S/Desktop$ cp file1.txt ziel.txt ; cat file2.txt | sed -e "s/:/\$:/1" | xargs
-l1 -I XXXX echo "s:\^XXXX:1" | xargs -l1 -I XXXX sed -e "XXXX" -i ziel.txt

xargs: Fehlendes korrespondierendes Anführungszeichen einfache; per Vorgabe sind Anführungszeichen für xargs bestimmt, sofern Sie nicht die Option -O verwenden

/mnt/c/Users/S/Desktop$ cp file1.txt ziel.txt ; cat file2.txt | sed -e "s/:/\$:/1" | xarg-l1 -I -O XXXX echo "s:\^XXXX:1" | xargs -l1 -I -O XXXX sed -e "XXXX" -i ziel.txt

xargs: XXXX: Datei oder Verzeichnis nicht gefunden

/mnt/c/Users/S/Desktop$ cp file1.txt ziel.txt ; cat file2.txt | sed -e "s/:/\$:/1" | xargs -l1 -I -0 XXXX echo "s:\^XXXX:1" | xargs -l1 -I -0 XXXX sed -e "XXXX" -i ziel.txt

xargs: XXXX: Datei oder Verzeichnis nicht gefunden

Fehler.... Problem: in der Datei 2 nach dem Doppelpunkt kommen nicht nur ASCII-Zeichen vor, sondern auch ö ü ß ä æ € ê é ó usw.
Mitglied: Lochkartenstanzer
Lochkartenstanzer 15.11.2017 aktualisiert um 10:28:27 Uhr
Goto Top
Moin,

Sind in den dateien außer dem Doppelpunkt Sonderzeichen wie z.b. Anfürhungsstriche, Hochkommate, Punkte etc.?

Dann mußt Du diese mit einem "Zwischenlauf" von "sed" auf die Dateie file2 mit einem bakshlash "\" escapen, wie Kollege Specht schon sagte.

Für den Punkt wäre das z.B.:

sed -e "s:\.:\\\\\.:g" oder so ähnlich. (Anzahl der bakslashes ggf. anpassen).

Für das Anführungszeichen echo "\"" | sed -e "s:\":\\\\\":g".


lks
Mitglied: 93578
93578 15.11.2017 aktualisiert um 10:29:17 Uhr
Goto Top
Ok. Jetzt habe ich kopiert. Ich probiere es.
Mitglied: Lochkartenstanzer
Lochkartenstanzer 15.11.2017 aktualisiert um 10:30:50 Uhr
Goto Top
Zitat von @93578:

Kann ich nicht, das sind zu viele... Russsich, Japanisch, Arabisch, Türkisch - ist alles dabei.


versuch mal für den Anfang einfach nur die Anführungszeichen zu secapen, indem du den obigen Befehl in die pipe mit einschmuggelst. face-smile


lks
Mitglied: 93578
93578 15.11.2017 um 10:44:40 Uhr
Goto Top
Wie kann es tun?

/mnt/c/Users/S/Desktop$ cp file1.txt ziel.txt ; cat file2.txt | sed -e "s:\":\\\\\":g" | sed -e "s/:/\$:/1" | x
args -l1 -I XXXX echo "s:\^XXXX:1" | xargs -l1 -I XXXX sed -e "XXXX" -i ziel.txt
xargs: Fehlendes korrespondierendes Anführungszeichen einfache; per Vorgabe sind Anführungszeichen für xargs bestimmt, sofern Sie nicht die Option -O verwenden
/mnt/c/Users/S/Desktop$ $ cp file1.txt ziel.txt ; cat file2txt | sed -e "s:\":\\\\\":g" | xargs -l1 -I XXXX ec
ho "s:\^XXXX:1" | xargs -l1 -I XXXX sed -e "XXXX" -i ziel.txt
bash: Syntaxfehler beim unerwarteten Wort »|«
Mitglied: Lochkartenstanzer
Lochkartenstanzer 15.11.2017 um 10:49:23 Uhr
Goto Top
dann ersetz mal die "einfachen" Anführungsstriche"

echo "\'" | sed -e "s:\':\\\\\':g"

lks
Mitglied: 93578
93578 15.11.2017 aktualisiert um 11:06:34 Uhr
Goto Top
???? Hab ich doch gemacht (siehe oben).

Normalerweise arbeite mit Regex und Emditor/Ultraedit so:

\.\:\*\'\#\' usw. Wie kann ich so was bei sed realisieren? Sorry , Linux ist für mich ein dunkler Wald.
Mitglied: 93578
93578 15.11.2017 um 11:50:07 Uhr
Goto Top
Wenn ich diese 2 Befehle einfüge, dann geht es trotzdem nicht:

cp file1.txt ziel.txt ; cat file2.txt | sed -e "s:\':\\\\\':g" | sed -e "s:\":\\\\\":g"
| sed -e "s/:/\$:/1" | xargs -l1 -I XXXX echo "s:\^XXXX:1" | xargs -l1 -I XXXX sed -e "XXXX" -i ziel.txt

xargs: Fehlendes korrespondierendes Anführungszeichen einfache; per Vorgabe sind Anführungszeichen für xargs bestimmt, sofern Sie nicht die Option -O verwenden
xargs: echo: wurde durch das Signal 13 abgebrochen.
Mitglied: 93578
93578 15.11.2017 um 12:46:02 Uhr
Goto Top
Mein Kollege hat es auch mal angeschaut. Er meinte: es geht nur mit Pyton. Zu viele Kombinationen von Sondernzeichen, die mit sed nicht abgedeckt werden können.

Vielen Dank an alle Beteiligte!