Seite 1 von 1
Leerzeilen einer Datei Entfernen
Verfasst: Dienstag 21. Juni 2016, 14:30
von shdw
Hallo liebe Community,
wie ihr seht, der hier ist mein erster Post. Ich arbeite hauptsächlich mit LUA, möchte ich aber auf Py umsteigen.
Nachdem ich 22 Seiten von diesem Forum durchgelesen, und leider die Antwort für mein "Problem" nicht gefunden habe, stelle ich euch meine Frage:
Ich habe eine datei, die heißt test (reine Text-Datei).
test Inhalt:
Meine Aufgabe hier ist die Leerzeile von der Datei zu entfernen und zu überschreiben.
Dafür habe ich ein kleines "Python Script" geschrieben:
Code: Alles auswählen
with open('/home/*******/test/test','w') as file:
for line in file:
ohneLeerzeilen = line.strip()
if ohneLeerzeilen:
file.write(ohneLeerzeilen)
print ohneLeerzeilen
Für mich macht das Sinn, für euch wahrscheinlich nicht. Tatsächlich wenn ich file.write(ohneLeerzeilen) auskommentiere, printet mir Python die Datei genauso wie ich sie haben möchte, überschreiben tut er sie nicht. mit 'w+' überschreibt er die Datei, allerdings mit nichts.
Vielen Dank im Voraus wenn ihr mir helfen könnt, wenn nicht, bedanke ich mich fürs lesen zumindest

.
Gruß
Shdw
Re: Leerzeilen einer Datei Entfernen
Verfasst: Dienstag 21. Juni 2016, 15:18
von Sirius3
@shdw: wenn Du Dateien im Modus 'w' öffnest, wird eine neue leere Datei erzeugt. Lesen schlägt dabei fehl (IOError: File not open for reading). Wenn Du die Datei zum Schreiben und Lesen öffnest 'w+', kannst Du zwar lesen und schreiben, das löst aber Dein Problem nicht wirklich, weil es nur ein Dateipositionszeiger gibt, so dass gleichzeitiges Lesen und Schreiben wahrscheinlich Quark ergibt. Dieses Verhalten ist Systembedingt, also Lua verhält sich da ganz ähnlich.
Das übliche Vorgehen ist es, eine neue Datei zu öffnen, aus der ersten Datei liest Du, in die zweite schreibst Du.
Re: Leerzeilen einer Datei Entfernen
Verfasst: Dienstag 21. Juni 2016, 15:54
von shdw
Yo!
ich dachte ich könnte die Datei lesen, bearbeiten und schreiben mit r+ oder w. Es ist leider nicht der Fall.
Das wäre meine Lösung dazu:
Code: Alles auswählen
with open('/home/*******/test/test_output','w') as output_file:
with open('/home/******/test/test_input','r+') as file:
for line in file:
ohneLeerzeile = line.strip()
if len(ohneLeerzeile) > 0:
file.write(ohneLeerzeile + "\n")
# print("*"+line+"*"+ohneLeerzeile+"*")
Ziemlich blöd, da ich das bräuchte nur um "unnötigen" Leerzeilen von .msg-Dateien (outlook Mails) die als .txt gespeichert werden (MIME encoding kann Cyrus nicht so gut verarbeiten. Wenn Mails wieder in Outlook eingebunden werden hat jede ursprüngliche Leerzeile sich mal 5 mutipliziert...).
Ich werde wahrscheinlich mit Bash mich beschäftigen müssen

Re: Leerzeilen einer Datei Entfernen
Verfasst: Dienstag 21. Juni 2016, 17:46
von Sirius3
@shdw: ich habe nicht geschrieben, dass es nicht geht (solange etwas gelöscht wird). Aber diese Operation in einer Datei auszuführen ist sehr viel komplexer und damit fehleranfälliger. Das 'r+' sollte übrigens ein 'r' sein, da Du nur lesen willst. «ohneLeerzeile» ist der falsche Name für die Variable, weil das nicht etwas ohne Leerzeilen ist, sondern diese Zeile soll ja darauf geprüft werden, ob es eine Leerzeile ist, oder nicht. Du löscht auch nicht nur Leerzeilen aus der Datei, sondern auch alle Leerzeichen am Anfang oder Ende der Zeile. Ist das so gewollt?
Sollten die Dateien nicht zu groß sein, kann man sie auch alternativ komplett in den Speicher lesen und dort bearbeiten.
Übrigens ist das Lesen und Schreiben etwas, das das Betriebsystem bereitstellt, da hilft Dir also auch nicht auf Bash auszuweichen, oder Lua oder sonst eine Programmiersprache.
Re: Leerzeilen einer Datei Entfernen
Verfasst: Dienstag 21. Juni 2016, 21:22
von shdw
@Sirius3
Ich verstehe, was du meinst...
Mein Fall ist der folgende: Ich benutze Cyrus Bboards um Mails von Outlook zu archivieren / als functional Mailbox (mehrere Personen dürfen darauf zugreifen usw).
Wenn z.B. Mails von Outlook in diese Mailboxen verschoben werden, speichert Cyrus diese als .txt im Server. Diese Dateien bleiben im Outlook-Cache für eine Weile, während sie noch im Cache sind, stimmt alles (Formatierung, Anhänge, Signaturen, usw...). Sobald diese Mails nicht mehr im Cache sind und man sie wieder öffnet, ist die ganze Formatierung am A.
Ein Beispiel vom OriginalMail
Code: Alles auswählen
Hallo Sirius3,
ich bedanke mich für deine Hilfe.
Viele Grüße
Shdw
und hier ein Beispiel vom nicht mehr gecachten Mail
Code: Alles auswählen
Hallo Sirius3,
ich bedanke mich für deine Hilfe.
Viele Grüße
shdw
Deswegen wollte ich ein Skript schreiben, der diese Leerzeilen einfach löscht und die selbe Datei überschreibt. Da viele Mails Anhänge haben, sind die .txt Dateien teilweise ziemlich groß.
Ich wollte eigentlich nur verstehen wie Python das macht um später eventuell eine Schleife zu erzeugen, die nicht ALLE Leerzeilen löscht, sondern erst prüft wenn eine Leerzeile von einer anderen gefolgt wird, nur eine davon gelöscht wird (sorry wg. des Ausdruckes, Deutsch ist nicht meine Muttersprache

).
Hoffentlich könntest du was dazu sagen, mich würde es interessieren wie du das besiegen würdest!
Gruß
shdw
Re: Leerzeilen einer Datei Entfernen
Verfasst: Dienstag 21. Juni 2016, 22:03
von Sirius3
@shdw: es ist übliches vorgehen, eine Datei nicht einfach zu überschreiben, weil bei einem Fehler Daten verloren gehen können. Ich glaube kaum, dass irgendein Programm Leerzeilen nach dem Zufallsprinzip einfügt. Statt also Symptome zu behandeln wäre es doch besser, nach der Ursache oder wenigstens nach einer Systematik zu suchen.
Re: Leerzeilen einer Datei Entfernen
Verfasst: Mittwoch 22. Juni 2016, 09:24
von noisefloor
Hallo,
Da viele Mails Anhänge haben, sind die .txt Dateien teilweise ziemlich groß.
Wobei eine Leerzeile normalerweise nur 1 oder 2 Bytes sind. D.h. effektiv Speicherplatz sparst du so kaum.
Gruß, noisefloor
Re: Leerzeilen einer Datei Entfernen
Verfasst: Mittwoch 22. Juni 2016, 12:56
von snafu
Zum Weglassen mehrerer Leerzeilen könnte man es so machen:
Code: Alles auswählen
def remove_multiple_blanks(lines):
lines = iter(lines)
for line in lines:
if not line.strip():
blank_line = line
for line in lines:
if line.strip():
# Found non-blank line
break
else:
# No more lines (EOF)
return
yield blank_line
yield line
def main():
text = 'Hallo Sirius3,\n\n\n\n\nich bedanke mich für deine Hilfe.\n\n\n\n\nViele Grüße\n\n\nshdw\n\n\n\n\n'
print('Original:')
print(text)
lines = text.splitlines(True)
clean_text = ''.join(remove_multiple_blanks(lines))
print('Bereinigt:')
print(clean_text)
if __name__ == '__main__':
main()
Hierbei werden alle Zeilen im Original ausgegeben, wenn in ihnen mindestens ein Zeichen enthalten ist, das nicht als Whitespace zählt (mit anderen Worten: wenn die Zeile beschrieben ist). Bei Leerzeilen wird die erste gefundene Leerzeile zurückgeliefert und alle direkt darauf folgenden Leerzeilen werden übersprungen. Leerzeilen am Textende, auf die keine beschriebene Zeile mehr folgt, werden ebenfalls übersprungen.
EDIT:
Der Quelltext ist relativ kurz, arbeitet aber auch mit diversen Sprachfeatures, die einem möglicherweise nicht gleich einleuchten, wenn man von einer anderen Programmiersprache kommt. Für einen Anfänger könnte es einfacher sein, wenn die eine oder andere Stelle mit etwas mehr Quelltext ausgedrückt wird. Spätestens dann sollte man den Code aber in mindestens eine weitere Funktion auslagern, wenn es übersichtlich bleiben soll.
Re: Leerzeilen einer Datei Entfernen
Verfasst: Mittwoch 22. Juni 2016, 13:30
von Sirius3
Statt verschachtelter for-Schleifen finde ich ein Flag übersichtlicher:
Code: Alles auswählen
def remove_multiple_blanks(lines):
skip_blank_lines = True
for line in lines:
blank_line = not line.strip()
if not skip_blank_lines or not blank_line:
yield line
skip_blank_lines = blank_line
Re: Leerzeilen einer Datei Entfernen
Verfasst: Mittwoch 22. Juni 2016, 13:53
von snafu
Klar, meine kürzere Variante wäre nahezu identisch:
Code: Alles auswählen
def remove_multiple_blanks(lines):
blank_seen = False
for line in lines:
blank = not line.strip()
if not blank or not blank_seen:
yield line
blank_seen = blank
Dann müsste man Leerzeilen am Dateiende nachträglich entfernen.
Re: Leerzeilen einer Datei Entfernen
Verfasst: Mittwoch 22. Juni 2016, 14:18
von Sirius3
@snafu: achso, da braucht es eine vor- und zurückschauende for-Schleife:
Code: Alles auswählen
def remove_multiple_blanks(lines):
non_blank_seen = blank_seen = False
for line in lines:
blank = not line.strip()
if not blank:
if non_blank_seen and blank_seen:
yield "\n"
yield line
non_blank_seen = True
blank_seen = blank
Re: Leerzeilen einer Datei Entfernen
Verfasst: Mittwoch 22. Juni 2016, 15:24
von BlackJack
Wobei ich die Idee mit dem erst mal schauen was dieses Phänomen verursacht immer noch am besten finde. Ich vermute mal irgendein beteiligtes Programm macht keinen sauberen Unterschied zwischen Text und Binärdateien und öffnet beim kopieren beispielsweise die Quelldatei im Binärmodus und schreibt dann im Textmodus. Da hat man unter Windows dann schnell mal etwas was nach zu vielen Zeilenumbrüchen aussieht.
Re: Leerzeilen einer Datei Entfernen
Verfasst: Mittwoch 22. Juni 2016, 16:13
von BlackJack
Ungetestet:
Code: Alles auswählen
from itertools import groupby
from operator import itemgetter
def collapse_blank_lines(lines):
for is_blank, group in groupby(
((not bool(line.strip()), line) for line in lines), itemgetter(0)
):
if is_blank:
yield '\n'
else:
for line in group:
yield line
Re: Leerzeilen einer Datei Entfernen
Verfasst: Mittwoch 22. Juni 2016, 21:45
von snafu
Wobei not bool(x) das selbe ist wie not x...
Re: Leerzeilen einer Datei Entfernen
Verfasst: Mittwoch 22. Juni 2016, 22:05
von BlackJack
@snafu: Du hast zielsicher die Stelle gefunden, an der ich ganz kurz vorm Absenden noch ein Schlüsselwort eingefügt hatte damit die Logik stimmt.

Re: Leerzeilen einer Datei Entfernen
Verfasst: Mittwoch 22. Juni 2016, 23:02
von snafu
Dachte ich mir schon, dass es ursprünglich mal ein
bool(...) war.
