In .txt Datei suchen

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
Eisi
User
Beiträge: 62
Registriert: Sonntag 24. November 2013, 21:59

Hallo zusammen,

Ich habe mal wieder ein Anliegen :mrgreen:

Ich habe eine Textdatei wo z.B "hallo" drin steht. Dank euch und dem Internet ist es mir ohne Probleme möglich nach einem String in der Datei zu suchen. Das Wort "hallo" wird in der Datei mit einer Variablen verbunden welche sich nun aber nicht direkt in der gleichen Zeile befindet sondern z.B. zwei drüber. Die Variable soll das Programm dann finden. Gibt es Möglichkeiten python zu sagen das er zwei Zeilen drüber nach der Variablen suchen soll die immer gleich anfängt z.B. "AB" gefolgt von einer Zahl die zufällig ist?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Die erste Frage, die sich stellt ist, ob die Datei so "kompliziert" aufgebaut sein muss.

Als Antwort kann man Dir nur sagen, dass man eigentlich nie direkt auf Dateien operiert, sondern auf Datenstrukturen. Je besser man die Bytes aus der Datei in höher gelagerte Konzepte transformiert (das nennt man parsen), desto einfacher ist die spätere Verarbeitung.

Du kannst natürlich mit einem RegExp nach einer solchen Stelle suchen, aber direkt einfach ist das imho aus dem Bauch heraus nicht. Einfacher wäre es, wenn Du den Text in eine geeignete Struktur parst und dazu einen Mechanismus baust, die eine solche Struktur wieder in eine Datei schreiben kann. XML-Parser tun z.B. nichts anderes, ähnliche wie JSON usw.

So würde ich hier wohl vorgehen.

(Aber zuerst die erste Frage beantworten! Evtl. hat man dann dieses Problem gar nicht!)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Eisi
User
Beiträge: 62
Registriert: Sonntag 24. November 2013, 21:59

danke für deine schnelle Antwort.

Die Datei ist kompliziert und verändern geht leider nicht. Grundlegend kann man aber sagen, wenn ich nach einem Wert in der Datei suche z.B. "test" das ein paar Zeilen weiter oben die dazugehörige Variable erscheint die anfangs immer gleich ist, z.B. 'S_A_' und sofort dahinter dann eine Zahl ist die sich je nach dem welchen Wert ich suche ändert.

Beispiel: Ich suche nach "test" und die dazugehörige Variable ist 'S_A_1' (Quasi die nächste "'S_A_" drüber).

Meine Idee war, ich suche test und das Programm geht solange weiter nach oben bis 'S_A_ kommt und packt dann nur die Ziffer dabei.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hyperion hat es schon kurz angeschnitten, aber du bist nicht weiter darauf eingegangen: Wie sieht denn die Struktur der Datei aus? Irgend ein strukturiertes Format ist doch wahrscheinlich gegeben. Da wäre es einfacher, wenn du die Daten zunächst parst, in vernünftige Datenstrukturen umsetzt und darauf dann die Suche durchführst.
Das Leben ist wie ein Tennisball.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Eisi hat geschrieben:Beispiel: Ich suche nach "test" und die dazugehörige Variable ist 'S_A_1' (Quasi die nächste "'S_A_" drüber).

Meine Idee war, ich suche test und das Programm geht solange weiter nach oben bis 'S_A_ kommt und packt dann nur die Ziffer dabei.
Warum liest du nicht einfach vorwärts, merkst dir jeweils das letzte "S_A_..." und verwendest es wenn dann später dein Suchbegriff kommt?
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Eisi hat geschrieben:Meine Idee war, ich suche test und das Programm geht solange weiter nach oben bis 'S_A_ kommt und packt dann nur die Ziffer dabei.
Ich würde nicht versuchen, in den Zeilen hin und her zu springen. Sobald Du auf ein Muster, das einem Namen entspricht ('S_A_') stößt, handelt es sich bei den Werten bis zum nächsten Namenstreffer ja wohl um den Bereich, in dem sich der gesuchte Wert ('test') befindet. Und so weiter...

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Eisi
User
Beiträge: 62
Registriert: Sonntag 24. November 2013, 21:59

/me hat geschrieben:
Eisi hat geschrieben:Beispiel: Ich suche nach "test" und die dazugehörige Variable ist 'S_A_1' (Quasi die nächste "'S_A_" drüber).

Meine Idee war, ich suche test und das Programm geht solange weiter nach oben bis 'S_A_ kommt und packt dann nur die Ziffer dabei.
Warum liest du nicht einfach vorwärts, merkst dir jeweils das letzte "S_A_..." und verwendest es wenn dann später dein Suchbegriff kommt?
Es kommt nicht Automatisch nach jedem S_A_ der Suchbegriff. Er wird noch anderweitig verwendet. Selbst wenn ich die S_A_'s kenne wäre es noch schwerer den Wert dafür zu finden weil er nur mit einem " ' " anfängt und das ist in dieser Datei bei anderen (für mich) uninteressanten Daten öfter der Fall. Der Suchbegriff ist ja eine Ziffernfolge eingefasst in " ' " z.B. '12346' deswegen kann man Ihn leicht finden. Man muss dann nur noch gucken Welche ist das letzte S_A_
BlackJack

@Eisi: Irgendwie scheint mir Dein Gegenargument keines zu sein. Du sollst ja nicht jedes 'S_A_' *verwenden* sondern dir nur immer das zuletzt gesehene *merken*. Und wenn dann der Suchbegriff kommt, brauchst Du nicht mehr rückwärts nach dem letzten 'S_A_' suchen, sondern Du hast Dir das letzte ja gemerkt und kannst es *dann* verwenden.
Eisi
User
Beiträge: 62
Registriert: Sonntag 24. November 2013, 21:59

hmm ja stimmt das könnte so gehen. dann guck ich mal wie ich das Code-technisch verwirkliche. sollte ich was gefunden habe schreib ich es hier rein
BlackJack

Also so ganz grob das Prinzip:

Code: Alles auswählen

def find(lines, needle):
    previous_sa = None
    for line in lines:
        if line.startswith('S_A_'):
            previous_sa = line
        elif needle in line and previous_sa is not None:
            yield previous_sa  # hier eventuell ``return``...
            # previous_sa = None  # ...oder das hier zusätzlich.
Eisi
User
Beiträge: 62
Registriert: Sonntag 24. November 2013, 21:59

Danke Blackjack für die Codehilfe. Als ich heute Nacht (mal wieder) über das erstellen des Programms gegrübelt habe kamen mir noch einige Ideen, die mich dann dazu bewegten nochmal alle verfügbaren .txt daten die damit zu tun haben mir anzuschauen. Es ist mir aufgefallen das es, wie ich jedenfalls denke, noch eine Datei gibt, die mir viel einfacher meine daten zur verfügung stellt. Die Datei besteht zum größten Teil aus einer immer gleichen Struktur.

[' 123456-1234' ' 1949' 614 0 1 [ 3000 2300][ -569336 798500 27000][ -61700 49100 18000][3 0 109 79 1][ 547 16797 13269] 'V13']

Ich suche nach 123456-1234 und er soll mir 3 0 109 79 1 am besten jede Zahl in einer Variablen abspeichern. Da 123456-1234 öfter vorkommt, interessiert mich nur das erste mal. Alles danach ist dann erstmal uninteressant. Wie kann man das in etwa verwirklichen?


Ich habe gerade gesehen das der Abstand immer gleich ist, egal welche zahlen zwischen den [ ] stehen. die [] sind immer gleich weit entfernt und wurden bei kürzeren zahlen mit leerzeichen gefüllt. vielleicht kann man damit arbeiten?
Kamik423
User
Beiträge: 93
Registriert: Donnerstag 28. März 2013, 16:53

Code: Alles auswählen

Import os
File = open(pfad, 'r')
Filetext = File.readline() ##falls du uir eine zeile (das heißt keine "enters") hast

Brackets = Filetext.split('][') ##das gibt dir die zahlen in den klammern in einer liste
for i in range(0, len(Brackets)-1):
     Brackets[i] = Brackets[i].split(" ") ##gibt dir eine liste [(3000,2300),(-569336,798500,27000),...]
                                          ##Damit kannst du dann machen was du willst 
                                          ##must sie aber vorher umwandeln, da sie string sind

Apostrophes = Filetext.split("'") ##gibt dir die nummern zwischen den anführungszeichen '
for i in range(len(Apostrophes)-1, 0, -1): ##zählt von hinten deine liste runter-->nur das letzte 
                                           ##(also für dich erste) zählt
     if Apostrophes[i] == "123456-1234":
          Index = i

##index ist die stelle in der 123456-1234 das erste mal auftritt


Falls ich deine dateistruktur richtig verstanden habe sollte das funktionieren
0x4c65742773206d616b652073757265207468617420686973746f7279206e6576657220666f726765747320746865206e616d6520656e746572707269736521
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

@Kamik423: An deinem Code ist eigentlich in jeder Zeile etwas verkehrt. Zunächst das "Import" in der ersten Zeile, was wohl eindeutig ein "import" sein sollte. Hinzu kommt, dass das os-Modul später nirgends verwendet wird. Anschließend öffnest du die Datei, ohne dass diese irgendwo regulär wieder geschlossen wird, geschweige denn in einem Fehlerfall. Zum Öffnen von Dateien sollte daher das with-Statement verwendet werden.

Dann verstoßen deine Namen gegen jede übliche Namenskonvention von Python, auch passt die Schreibweise zu keiner anderen Sprache. Schau dir dazu mal den Styleguide an. Auch deine Namen sind nichtssagend gewählt. "File" ist total generisch, "Filetext" könnte auch einfach text, data oder content heißen, das Präfix ist total überflüssug. "Brackets" ist mindestens irreführend gewählt, da stecken ja gerade keine Klammern drin.

``for i in range(len(x))`` ist in Python ein Anti-Pattern. Wenn range in Verbindung mit len verwendet wird, dann ist das in der Regel falsch. Man kann direkt über Listen iterieren und muss nicht den Umweg über Indizes gehen. Wenn man doch mal den Index braucht, dann verwendet man dazu die enumerate-Funktion. Auch ist die Angabe der 0 als erster Parameter bei range überflüssig. Selbiges gilt auch für die zweite for-Schleife.

Auch in "Apostrophes" stecken wieder keine Apostrophe drinen, sondern Zahlen als Strings. Dabei fällt natürlich auch auf, dass der dazugehörige Kommentar fehlerhaft ist. Nummern sind etwas anderes als Zahlen.

Auch ist dein Programm fehlerhaft, falls es keinen Match gibt. Wird später im Programm "Index" verwendet, so wird ein NameError geworfen, da es nie definiert wurde. Ganz abgesehen davon bricht dein Programm zusammen, falls sich irgendwo Hochkommas im Fließtext befinden, dann funktioniert dein "Parsen" nicht mehr. Gleiches gilt, wenn die Strings stattdessen in Doppelten Anführungszeichen sind. Um ein vernünftiges Parsen kommt man nicht herum. Wenn deine Implementierung mal funktioniert, dann ist das eher reine Glücksache.
Das Leben ist wie ein Tennisball.
Kamik423
User
Beiträge: 93
Registriert: Donnerstag 28. März 2013, 16:53

EyDu hat geschrieben:@Kamik423: An deinem Code ist eigentlich in jeder Zeile etwas verkehrt. Zunächst das "Import" in der ersten Zeile, was wohl eindeutig ein "import" sein sollte. Hinzu kommt, dass das os-Modul später nirgends verwendet wird. Anschließend öffnest du die Datei, ohne dass diese irgendwo regulär wieder geschlossen wird, geschweige denn in einem Fehlerfall. Zum Öffnen von Dateien sollte daher das with-Statement verwendet werden.
Entschuldigung, ich habe das mit meinem ipad geschrieben, das autokapitalisiert, d.h. Setzt einen Großbuchstaben am zeilenanfang. Import ist überflüssig, außer du benutzt os um den Pfad anzugeben. Schließen habe ich vergessen, entschuldigung :(
EyDu hat geschrieben:Dann verstoßen deine Namen gegen jede übliche Namenskonvention von Python, auch passt die Schreibweise zu keiner anderen Sprache. Schau dir dazu mal den Styleguide an. Auch deine Namen sind nichtssagend gewählt. "File" ist total generisch, "Filetext" könnte auch einfach text, data oder content heißen, das Präfix ist total überflüssug. "Brackets" ist mindestens irreführend gewählt, da stecken ja gerade keine Klammern drin.
Ja, die Großbuchstaben wurden autogesetzt, und ich habe sie nicht geändert. Entschuldigung. Auch meine Namensgebung war nicht wirklich überdacht.
Brackets: an den klammern gesplitted.
EyDu hat geschrieben:``for i in range(len(x))`` ist in Python ein Anti-Pattern. Wenn range in Verbindung mit len verwendet wird, dann ist das in der Regel falsch. Man kann direkt über Listen iterieren und muss nicht den Umweg über Indizes gehen. Wenn man doch mal den Index braucht, dann verwendet man dazu die enumerate-Funktion. Auch ist die Angabe der 0 als erster Parameter bei range überflüssig. Selbiges gilt auch für die zweite for-Schleife.
Ich benutzte len() um mit Nummern zu iterieren um Indizes angeben zu können, um Bracket[index] auf einen wert setzten zu können. Ich kannte die enumerate funktion nicht. Auch benutze ich" in range" nicht sehr oft, und habe daher das mit der 0 vergessen.
EyDu hat geschrieben:Auch in "Apostrophes" stecken wieder keine Apostrophe drinen, sondern Zahlen als Strings. Dabei fällt natürlich auch auf, dass der dazugehörige Kommentar fehlerhaft ist. Nummern sind etwas anderes als Zahlen.
Apodtrophes: selbes wie oben.
Was ist der unterschied?
EyDu hat geschrieben:Auch ist dein Programm fehlerhaft, falls es keinen Match gibt. Wird später im Programm "Index" verwendet, so wird ein NameError geworfen, da es nie definiert wurde. Ganz abgesehen davon bricht dein Programm zusammen, falls sich irgendwo Hochkommas im Fließtext befinden, dann funktioniert dein "Parsen" nicht mehr. Gleiches gilt, wenn die Strings stattdessen in Doppelten Anführungszeichen sind. Um ein vernünftiges Parsen kommt man nicht herum. Wenn deine Implementierung mal funktioniert, dann ist das eher reine Glücksache.
Yupp, ich habe vergessen index zu definieren. Parsen mit hochkommas funktioniert für mich...
Ich entschuldige mich nocheinmal für mein fehlerhaftes programm. Ich wollte nur helfen... :( :?
Danke fürs aufzeigen meiner fehler
0x4c65742773206d616b652073757265207468617420686973746f7279206e6576657220666f726765747320746865206e616d6520656e746572707269736521
Eisi
User
Beiträge: 62
Registriert: Sonntag 24. November 2013, 21:59

Kennt jemand eine andere Version? Oder kann man die trotz der Fehler nehmen?
BlackJack

@Eisi: Man könnte sich selbst etwas schreiben, oder zumindest nachvollziehen ob die Lösung die man übernehmen möchte, tatsächlich das Problem auf eine Art löst die robust genug ist.

Vielleicht bin ich aber auch nur zu sehr Perfektionist. Ich würde versuchen ob man das Datenformat nicht parsen kann, statt da auf Textebene Daten zu extrahieren. Sieht ja irgendwie nach etwas Lisp oder Scheme ähnlichen aus, nur mit eckigen Klammern statt runden.
Eisi
User
Beiträge: 62
Registriert: Sonntag 24. November 2013, 21:59

Ich habe noch nie etwas mit parsen gemacht und dementsprechend keine Ahnung wie sowas geht. Aber denke bei Google werde ich da fündig
Antworten