Nächste Zeile ausgeben lassen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
trbo
User
Beiträge: 10
Registriert: Mittwoch 29. April 2015, 08:48

Liebe Python Freund,

ich habe ein kleines Problem mit einem eigentlich doch sehr einfachen Programm. Ich durchsuche hier eine .txt Datei nach einem bestimmten Schlüssel und möchte mir die Zeile nach jener in der der Schlüssel gefunden wurde ausgeben lassen. Nachdem es nach ewigem rumprobieren jedoch immer noch nicht klappt hoffe ich hier auf Hilfe

hier mal der Code

Code: Alles auswählen

Journal=open('J_15April.txt')

jrn=Journal.read()

Zeile=jrn.split('14.04.2015')


for line in Zeile:
    if 'BON' in line:
        
        print(line)

Mfg

trbo
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Irgendwie sieht dein Ansatz merkwürdig aus. Was du line nennst ist keine Zeile, sondern die Teile der Datei, die jeweils vor und nach deinem Suchbegriff '14.04.2015' stehen. Diese Teile können beliebig viele Zeilen umfassen. Eventuell ist deine Beschreibung auch unvollständig, dann müsstest du das noch einmal erklären.

Bei der Gelegenheit sollte man dann auch gleich dafür sorgen, dass die geöffnete Datei wieder geschlossen wird. Das geht entweder über ein explizites close oder automatisch wenn du das with-Statement beim Öffnen verwendest.

Code: Alles auswählen

with open('J_15April.txt') as journal:
    for line in journal:
        if 'BON' in line:
            print(next(journal))
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@trbo
1. Wenn Du eine Datei via dem with statement öffnest, wird die Datei auch wieder ordnungsgemäß geschlossen, ohne dass Du Dich weiters darum kümmern musst.

2. Wenn Du die Datei mit `read()` einliest, bekommst Du deren gesamten Inhalt, was man nicht immer möchte und in Deinem Fall auch keinen Sinn macht, da Du ja eine bestimmte Zeile suchst. Ich würde also zu `readline()` raten.

3. Nachdem man über file objects direkt iterieren (Element für Element abrufen, im Falle einer Datei Zeile für Zeile) kann, kannst Du folgendes machen:

Code: Alles auswählen

with open('J_15April.txt') as journal:
    for line in journal:
        if 'BON' in line:
            print(line)
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@mutetella: Gefragt war allerdings die *nachfolgende* Zeile. ;)
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@snafu
Und ich wollte gerade nachhaken, was denn das `next()` da soll... :)

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
nezzcarth
User
Beiträge: 1635
Registriert: Samstag 16. April 2011, 12:47

@me: Ich weiß nicht, ob das in der Datei vorkommt, aber für den speziellen Fall, dass das Schlüsselwort in zwei aufeinander folgenden Zeilen steht, würde dein Vorschlag glaube ich nicht das gewünschte(?) Ergebnis liefern. Vielleicht könnte man das mit einer Zustandsvariable lösen.
Zuletzt geändert von nezzcarth am Mittwoch 6. Mai 2015, 10:22, insgesamt 1-mal geändert.
BlackJack

@nezzcarth: Das könnte man mit einer Funktion lösen die über ein ”Fenster” iteriert:

Code: Alles auswählen

#!/usr/bin/env python
from __future__ import absolute_import, division, print_function
from collections import deque
from itertools import islice


def iter_window(iterable, window_length):
    items = iter(iterable)
    window = deque(islice(items, window_length - 1), window_length)
    for item in iterable:
        window.append(item)
        yield list(window)


def main():
    with open('test.txt') as lines:
        for line, next_line in iter_window(lines, 2):
            if 'BON' in line:
                print(next_line)


if __name__ == '__main__':
    main()
Ist etwas komplexer als eine Zustandsvariable, dafür ist es universeller und wenn man die `iter_window()`-Funktion mal geschrieben hat kann man sie auch an anderer Stelle wiederverwenden.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Um mal diverse Eventualitäten abzudecken:

Code: Alles auswählen

from itertools import tee

def get_lines(infile, key):
    line_iters = tee(infile)
    try:
        next(line_iters[1])
    except StopIteration:
        return
    for line, next_line in zip(*line_iters):
        if key in line:
            yield next_line

def main():
    with open('J_15April.txt') as infile:
        lines = get_lines(infile, 'BON')
        print('\n'.join(lines))

if __name__ == '__main__':
    main()
BlackJack

@snafu: Das ist jetzt aber vom Ergebnis das gleiche wie die vier Zeilen von /me.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@BlackJack: Nein. Ich bezog mich vor allem auf den Einwand von nezzcarth, dass bei der simplen Lösung mit `next()` Zeilen übesprungen werden, wenn dass Schlüsselwort in zwei aufeinanderfolgenden Zeilen enthalten ist. Durch die Lösung mit zwei Iteratoren umgeht man dieses Problem. Außerdem schmeißt mein Code keine `StopIteration`, falls die Datei leer ist.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@BlackJack
Müsste es, um nezzcarth's Einwand zu lösen, nicht

Code: Alles auswählen

...
            if 'BON' in line and 'BON' not in next_line:
                print(next_line)
heißen?

Ausgehend von einer Datei

Code: Alles auswählen

BON
BON
Treffer
BON
BON
BON
Treffer
erhalte ich ohne ``... not in ...``

Code: Alles auswählen

BON
Treffer
BON
BON
Treffer
als Ergebnis. Mit einem zusätzlichen ``... not in ...``:

Code: Alles auswählen

Treffer
Treffer
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Es wäre auch interessant, was der Threadersteller eigentlich möchte. Vielleicht reicht ihm die von /me gezeigte Variante ja schon aus.

mutetella's Sichtweise des Problems geht ja schon mehr in Richtung State Machine. Das kann man zwar durchaus so implementieren, aber vielleicht wird es gar nicht in diesem Umfang benötigt...
Antworten