Bei mir erschienen Artikel in der Beitragsübersicht und unter den Zählmarken doppelt oder sogar zigfach. Der Grund war das Prosodia-Plugin, das viele doppelte Zeilen in einer Tabelle hatte. Aber wie bereinigt man diese Duplikate?
Händisch? In einem 12 MB großen SQL-Dump? Eher nicht. Da sitze ich ja tagelang dran! Ich konnte auch keine Tools finden, die MySQL-Dumps bereinigen. Mist.
Aber es geht ganz schnell mit einem Python-Script:
import os # Benutzeraufforderung zur Eingabe der Quelldatei input_file = input("\nThe input file will \033[91m\033[1mNOT\033[0m be modified! \nAn output file and a file with the deleted data will be created. If they already exist, they will be overwritten without confirmation!\nPlease provide the path to the input file: ").strip() # Überprüfen, ob die Datei existiert if not os.path.isfile(input_file): print(f"The file '{input_file}' does not exist. Please check the path.") exit(1) # Automatische Generierung der Ausgabedateien output_file = f"{os.path.splitext(input_file)[0]}_cleaned{os.path.splitext(input_file)[1]}" deleted_file = f"{os.path.splitext(input_file)[0]}_deleted{os.path.splitext(input_file)[1]}" # Set zur Speicherung eindeutiger Zeilen seen_lines = set() # Zähler für die Zeilen written_lines = 0 deleted_lines = 0 # Ermitteln der Größe der Eingabedatei in Bytes input_size = os.path.getsize(input_file) # Hilfsfunktion zur Formatierung der Dateigrößen im US-Format def format_size(size_in_bytes): if size_in_bytes < 1024: return f"{size_in_bytes:,.2f} bytes" elif size_in_bytes < 1048576: return f"{size_in_bytes / 1024:,.2f} KB" elif size_in_bytes < 1073741824: return f"{size_in_bytes / 1048576:,.2f} MB" else: return f"{size_in_bytes / 1073741824:,.2f} GB" try: with open(input_file, mode="r", encoding="utf-8") as infile, \ open(output_file, mode="w", encoding="utf-8") as outfile, \ open(deleted_file, mode="w", encoding="utf-8") as dfile: for line in infile: # Behalte Leerzeilen in der Ausgabe if line.strip() == "": outfile.write(line) # Leerzeile unverändert ausgeben continue # Zeile ohne Duplikate in die Ausgabedatei schreiben if line not in seen_lines: outfile.write(line) seen_lines.add(line) # Markiere Zeile als gesehen written_lines += 1 else: deleted_lines += 1 # Zähle gelöschte Duplikate dfile.write(line) # Schreibe gelöschte Zeilen in die separate Datei # Optional: Ein Ausschnitt der aktuell bearbeiteten Zeile ausgeben (max. 100 Zeichen) print(f"Processing line: {line[:100]}...") # Zeige die ersten 100 Zeichen der Zeile # Ermitteln der Größe der Ausgabedatei in Bytes output_size = os.path.getsize(output_file) deleted_size = os.path.getsize(deleted_file) # Berechnungen, wie viele Daten entfernt wurden size_difference = input_size - output_size # Berechnen des Anteils der gelöschten Daten in % deleted_percentage = (deleted_size / input_size) * 100 if input_size > 0 else 0 # Ausgabe der finalen Informationen print(f"\n\n\033[0m*********** F I N I S H E D ***********") print(f"\nInput file: \033[91m\033[1m{input_file}\033[0m") print(f"Cleaned file: \033[91m\033[1m{output_file}\033[0m") print(f"Deleted content file: \033[91m\033[1m{deleted_file}\033[0m") print(f"\n\033[91m\033[1m{deleted_lines:,}\033[0m duplicate lines have been successfully removed.") print(f"Number of output lines: \033[91m\033[1m{written_lines:,}\033[0m") print(f"\nInput file size: \033[91m\033[1m{format_size(input_size)}\033[0m") print(f"Cleaned file size: \033[91m\033[1m{format_size(output_size)}\033[0m") print(f"Deleted data size: \033[91m\033[1m{format_size(deleted_size)}\033[0m") print(f"Deleted data percentage: \033[91m\033[1m{deleted_percentage:,.2f}%\033[0m") print(f"\nPlease check the output files!") print(f"\nGood luck! \n") except Exception as e: print(f"Oops! An error occurred: \033[91m\033[1m{e}\033[0m")
Den Code kopieren und in einem Texteditor Eurer Wahl kopieren. Das Script unter einem Namen wie „abspeichern. Das Script unter Eigenschaften noch als Programm ausführbar machen und dann starten.
Auch bei großen Dumps geht das so schnell, dass man sich verwundert fragt, ob überhaupt etwas durchgelaufen ist. :-)
Natürlich funktioniert dieses Script auch mit anderen Dateien. wie .txt oder .csv. Denkt daran, vor dem Einsatz des Skripts eine Sicherheitskopie Eurer Originaldatei zu erstellen – sicher ist sicher!
Hintergrund
Wie ändere ich einen SQL-Dump ohne lokal installiertes MySQL und phpMyAdmin? Schwierig! Also habe ich Prosodia die Zahlmarken-Tabellen als .csv exportieren lassen. Wir reden hier von Tabellen, in denen obendrein noch der komplette Text aller Artikel gespeichtert ist. Unhandlich ist nicht das richtige Wort. Auch Libre Office Calc streicht hier die Segel:
Im Phyton-Script habe ich es dann mit Tabellenfunktionen wie csv.field_size_limit, unique_rows, header, csv.reader, delimiter, quotechar, skipinitialspace und all so einem Kram versucht.
Das führte zu einem totalen Chaos und mit jeder Anpassung wurde es schlimmer und schlimmer! Eine andere Lösung musste her. Eine einfachere Lösung musste her!
Womit bearbeite ich normalerweise Skripte oder Dumps? Richtig! Mit gedit! Und wenn sie größer sind? Mit kate! Das sind beides Texteditoren. Und ein SQL-Dump ist am Ende auch nur Text!
In meinem Fall war die einfachste Methode – mit der Datei als Textdatei zu arbeiten, ohne sich mit Tabellenfunktionen oder komplexeren Datenstrukturen zu beschäftigen – die beste Lösung.
Wenn ich die Datei als reine Textdatei behandle, kann ich die Zeilen eins zu eins vergleichen und doppelte Zeilen löschen, ohne mich um CSV-Parsing, Quoting oder Feldtrennzeichen kümmern zu müssen. Keep it simple!