String in Text suchen und Satz ausgeben

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.
harvey186
User
Beiträge: 20
Registriert: Mittwoch 14. Dezember 2016, 08:20

Hi,
ich habe ein Problem, ich möchte in einem Text nach einem bestimmten Wort suchen und dann den Satz, in dem das Wort steht ausgeben. Ich habe es geschafft, dass das Wort gefunden wird und alles was danach steht bis zum nächsten Punkt . ausgegeben wird. Aber wie schaffe ich es , dass auch der Text vor dem Wort bis zum nächsten Punkt ausgegeben wird, also der ganze Satz ?? Gibt es sowas wie read (back) ?
Hier mein derzeitiger code

Code: Alles auswählen

#!/usr/bin/python3.6
# coding: utf-8

import re

def suchen(regAusdruck, textdatei):
    f = open(textdatei, 'r', encoding = 'latin-1')
    rfctext = f.read()
    f.close()
    return re.findall(regAusdruck, rfctext)

pattern1 = r'\bLuzifer\b[^.;:!?]{2,}' 
print(suchen(pattern1, "tale.txt"))
Danke
Zuletzt geändert von Anonymous am Mittwoch 14. Dezember 2016, 12:12, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@harvey186: Wenn Du so bis zum Ende des Satzes suchst, dann sollte doch die Erweiterung "vom Anfang des Satzes" kein Problem sein. Warum darf man nicht nach dem letzten Wort eines Satzes suchen?
harvey186
User
Beiträge: 20
Registriert: Mittwoch 14. Dezember 2016, 08:20

Das verstehe ich jetzt nicht. Es geht mir darum, wenn das Suchwort mitten im Satz steht, gibt mein Code nur den Text vom Suchwort bis zum nächsten Punkt aus, aber nicht das, was VOR dem Suchwort steht.
Also, wenn der Satz lautet:
Das Leben ist schön.
und das Suchwort "Leben" ist, dann gibt mein script nur: "Leben ist schön" aus, aber nicht das "Das" .

und was ist mit <Warum darf man nicht nach dem letzten Wort eines Satzes suchen?> gemeint ??
BlackJack

Wenn das Wort das letzte im Satz ist, wird es nicht gefunden:

Code: Alles auswählen

In [4]: re.findall(r'\bLeben\b[^.;:!?]{2,}', 'Schön ist das Leben.')
Out[4]: []

In [5]: re.findall(r'\bLeben\b[^.;:!?]{2,}', 'Das Leben ist schön.')
Out[5]: ['Leben ist sch\xc3\xb6n']
Ich würde es ja in zwei Schritte aufteilen: Aufteilen des Textes in Sätze. Und dann in jedem Satz das Wort suchen. Wenn man versucht in regulären Ausdrücken zu clever zu werden, bekommt man unlesbare Zeichensuppe im Quelltext die schlecht wart- und erweiterbar ist, und teilweise dann auch in bestimmten Randfällen, an die man nicht gedacht hat, nicht so funktioniert wie man das möchte.
harvey186
User
Beiträge: 20
Registriert: Mittwoch 14. Dezember 2016, 08:20

Ja, stimmt, wenn es am Satzende steht, wird es nicht ausgegeben.

Das mit dem Teilen ist garnicht so schlecht. Werd ich mal probieren.

By the way, wie bekomme ich bei der Ausgabe dieses hier weg auÃ\x9ferhalb. Also das ß ausgeschrieben. Latin-1 klappt nicht.
BlackJack

@harvey186: Mein System ist auf UTF-8 eingestellt. Bei Text sollte man sowieso am besten mit Unicode-Zeichenketten arbeiten und nicht mit Bytezeichenketten. Also hätte mein Beispiel so aussehen sollen:

Code: Alles auswählen

In [6]: re.findall(r'\bLeben\b[^.;:!?]{2,}', u'Schön ist das Leben.')
Out[6]: []

In [7]: re.findall(r'\bLeben\b[^.;:!?]{2,}', u'Das Leben ist schön.')
Out[7]: [u'Leben ist sch\xf6n']
Edit: Und für Deinen Code bedeutet das Du musst bei `encoding` auch die tatsächliche Kodierung angeben in der dieser Text gespeichert ist. Scheint mir auch UTF-8 zu sein.
harvey186
User
Beiträge: 20
Registriert: Mittwoch 14. Dezember 2016, 08:20

Super Danke. Werd mich heut Abend ma dran machen.
harvey186
User
Beiträge: 20
Registriert: Mittwoch 14. Dezember 2016, 08:20

ich versteh das alles nicht :(
Mein Text (tale.txt):
Im Jahr 1895 wird einem jungen Einwandererpaar auf Ellis Island die Einreise in die USA verweigert, weil beide an der Tuberkulose erkrankt sind. Als ihrem kleinen Sohn auch ohne sie die Einreise verweigert wird, beschließen sie, ihn in ein Modellsegelboot mit dem Namen Stadt der Gerechtigkeit zu setzen, in der Hoffnung, das Kind werde gefunden.
1916 ist das Kind zu einem Mann herangewachsen. Er nennt sich Peter Lake. Peter wurde von dem Gangsterboss Pearly Soames aufgezogen und verdient sich seinen Lebensunterhalt nun als Einbrecher und Dieb. Als Peter beschließt, Pearlys Bande und sein altes Leben zu verlassen, macht er sich seinen Ziehvater zum wütenden Gegner und wird von dessen Bande gejagt.

Mein Code um satzweise den Text in tale1.txt zu speichern

Code: Alles auswählen

#!/usr/bin/python3.6
# coding: utf-8

import re

def suchen(regAusdruck, textdatei):
    f = open(textdatei, 'r', encoding = 'utf-8')
    rfctext = f.read()
    f.close()
    return re.findall(regAusdruck, rfctext)


fobj_in = open("tale.txt")
fobj_out = open("tale1.txt","w")
i = 1
for line in fobj_in:
    txt = str(i)
    txt1 = str(line.split("."))
    fobj_out.write(txt + ": " + txt1)
    i = i + 1
fobj_in.close()
fobj_out.close()
Der text wird getrennt, aber nicht beim Punkt, sondern beim Absatz ?!!?
tale1.txt:
1: ['Im Jahr 1895 wird einem jungen Einwandererpaar auf Ellis Island die Einreise in die USA verweigert, weil beide an der Tuberkulose erkrankt sind', ' Als ihrem kleinen Sohn auch ohne sie die Einreise verweigert wird, beschließen sie, ihn in ein Modellsegelboot mit dem Namen Stadt der Gerechtigkeit zu setzen, in der Hoffnung, das Kind werde gefunden', '\n']2: ['1916 ist das Kind zu einem Mann herangewachsen', ' Er nennt sich Peter Lake', ' Peter wurde von dem Gangsterboss Pearly Soames aufgezogen und verdient sich seinen Lebensunterhalt nun als Einbrecher und Dieb', ' Als Peter beschließt, Pearlys Bande und sein altes Leben zu verlassen, macht er sich seinen Ziehvater zum wütenden Gegner und wird von dessen Bande gejagt',
Zuletzt geändert von Anonymous am Mittwoch 14. Dezember 2016, 18:03, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@harvey186: wenn Du die Datei zeilenweise einliest, dann endet mit dem Ende einer Zeile auch ein Satz. Statt die Ausgabe mit str und + zusamenzustückeln solltest Du .format benutzen. Dateien öffnet man am Besten mit einem with-Statement.
harvey186
User
Beiträge: 20
Registriert: Mittwoch 14. Dezember 2016, 08:20

@Sirius3: Ok, danke, aber deine Antwort hilf mir nun wirklich nicht weiter. Keine Ahnung was ich mit .format mahen soll und wie das mir dabei hilft, den Text Satzweise zu speichern.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Python hat eine umfangreiche Dokumentation und auch viele Drittquellen behandeln die Sprache. Eigentlich müsstest du nur Google mit den Stichwörtern füttern, die dir hier gegeben werden. Ein bißchen Eigeninitiative in Bezug auf Recherche und Umsetzung erwarten wir hier schon. Sonst lernst du nichts dabei. Das alles kann dann auch schon mal ne Stunde länger dauern als gedacht, aber so ist das nunmal beim Programmieren.
harvey186
User
Beiträge: 20
Registriert: Mittwoch 14. Dezember 2016, 08:20

Danke snafum ich bin ganz deiner Meinung. Nach nun fast 4 Tagen googeln, lesen, ausprobieren hab ich mich hier angemeldet und mein Anliegen in der Hoffnung auf Hilfe gepostet.
BlackJack

@harvey186: Beobachtung: Die Absätze sind offenbar durch Zeilnenenden in der Datei gekennzeichnet. Da stellt sich dann als erstes die Frage ob man sich darauf verlassen kann/darf, denn das muss ja nicht so sein. Es gibt auch Textdateien bei denen auch innerhalb von Absätzen Zeilenenden vorkommen.

Sollte man sich darauf verlassen können/dürfen, dann sollte man als erstes `line` in `paragraph` umbenennen, damit diese Erwartungshaltung an die Textdatei auch im Programm deutlich wird, also im Quelltext auch dokumentiert ist.

Die Schleife macht einmal pro *Absatz* etwas. Wenn da dann einfach nur *ein* `write()`-Aufruf pro Absatz ausgeführt wird, so wie er das jetzt gerade wird, dann wird der ganze Absatz geschrieben. So wie Du das jetzt gerade durchführst, als Zeichenkettendarstellung einer Liste. Das ist nicht gut, weil nicht sinnvoll, weil man das nicht wieder einfach und vernünftig eingelesen bekommt. Du schreibst ausserdem nichts in die Datei was die einzelnen Absätze voneinander trennen würde. Das steht dort alles direkt hintereinander in der Datei, ohne Zeilenendezeichen um mindestens mal die Absätze zu trennen, die geschrieben werden.

Wenn Du beispielsweise eine Zeile pro Satz in der Ergebnisdatei haben möchtest, dann musst Du auch Code schreiben der genau das tut: eine Zeile pro Satz schreiben. Also die Daten/Zeichen der Zeile, und dann ein Zeilenendezeichen dahinter. Die kommen da nicht auf magische Weise hin, ausser man verwendet zum Beispiel `print()` mit dem entsprechenden Argument für die Ausgabedatei. Das ist dann auch nicht magisch, sondern das dokumentierte Verhalten von `print()`.

Alternativ kann man alle Sätze auf einmal schreiben wenn man vorher dafür gesorgt hat, dass man eine Zeichenkette hat, in der alle Sätze enthalten und mit einem Zeilenendezeichen abgeschlossen sind.

Die `format()`-Methode hilft grundsätzlich les- und wartbareren Code zu schreiben, gegenüber dem umwandeln von Einzelteilen mittels `str()` die man dann mit ``+`` zusammenstückelt. Aber was auch immer Dich da glücklicher macht: Du willst keine Listen in ihre Zeichenkettendarstellung umwandeln und irgendwo speichern, ausser vielleicht zur Fehlersuche in einer Logdatei. Das Format ist nicht für Endanwender gedacht.

Hast Du denn schon mal ein Tutorial durchgearbeitet? In der Python-Dokumentation gibt es eines.
harvey186
User
Beiträge: 20
Registriert: Mittwoch 14. Dezember 2016, 08:20

Danke für die Erläuterung. Und ja, mein bescheidenes Wissen hab ich nur aus Tuturials und googeln und naürlich ausprobieren.
Aber ein Tutorial für read (back) oder so, habe ich nicht gefunden. Ich habe zwischenzeitlich viel geschafft, aber wie ich ganz am Anfang gepostet habe, finde ich nirgends und ich hab wirklich Tage gegoogelt, wie ich von meinem gesuchten Wort zum Satzanfang finden und ausgeben kann.

Wenn du mir also einen Tipp geben kannst, wo ich eine passende Doku finden kann, lese ich mich da gerne rein.
BlackJack

@harvey186: *Die* passende Dokumentation und *das* passende Tutorial zu genau *diesem* sehr speziellen Problem wird es wohl nicht geben. Das Tutorial in der Python-Dokumentation und die Python-Dokumentation sollte Dich aber in die Lage versetzen das Problem zu lösen. Programmieren funktioniert nicht so, dass man immer Lösungen zu den exakten Problemen im Internet sucht. Das wird nicht funktionieren. Tutorials sind auch nicht zum lösen von konkreten Problemen da, sondern um den Umgang mit Werkzeugen wie beispielsweise einer Programmiersprache allgemein oder speziellen Bibliotheken zu lernen, so dass man dann selbst eine ganze Klasse von Problemen lösen kann.

Für die Aufgabe eine Textdatei mit Absätzen pro Zeile in eine zu überführen die einen Satz pro Zeile enthält, reichen Dateiobjekte, Zeichenketten, Schleifen, eventuell noch bedingte Ausführung, und Funktionen vollkommen aus. Das wird alles in der Python-Dokumentation behandelt. Die Grundlagen im Tutorial und die Details zu den Datentypen und den Operationen die darauf zur Verfügung stehen im Referenzteil (API und Sprache).

Programmieren besteht dann darin das Wissen über die Datentypen und Operationen sinnvoll zu einem Programm zusammen zu setzen. Dabei macht es Sinn das Problem in Teilprobleme zu zerlegen zu denen man Teillösungen schreiben kann. Also immer weiter zerlegen bis man die Teilprobleme in Funktionen mit ein paar Zeilen lösen kann. Diese Teillösungen kann man dann implementieren und testen. Wenn eine Teillösung das macht was sie soll, kann man zum Implementieren der nächsten Teillösung weitergehen und die testen. So eine Teillösung kann eventuell schon vorher implementierte verwenden. Das macht man dann solange bis man eine Gesamtlösung hat.

Du versuchst da alles irgendwie auf einmal zu lösen, in einem grossen¹ Code-Klumpen auf Modulebene, und bei dem Punkt wo Du einen Absatz schon (fast) in Sätze aufgeteilt hast, eine Abkürzung zu nehmen in dem Du die Liste mit den Sätzen mit `str()` in eine Zeichenkettendarstellung umwandelst in der falschen Annahme da wird schon auf magische Weise das herauskommen was Du haben möchtest und keine Zeichenkettendarstellung einer Liste wie das sonst passiert wenn man Listen nach einer Zeichenkettendarstellung fragt.

Eine Zerlegung kann hier Beispielsweise so aussehen: Eine Funktion die einen Dateinamen bekommt und die Zeilen aus der Datei als Liste mit Absätzen zurück gibt. Eine Funktion die eine Liste mit Absätzen bekommt und eine Liste mit Sätzen zurück gibt. Die muss mit jedem Absatz das gleiche machen, nämlich den in Sätze zerlegen und zum Ergebnis hinzufügen. Dafür wäre eine Funktion nützlich die eine Zeichenkette mit einem Absatz bekommt und eine Liste mit Sätzen zurück gibt.

____
¹ Wirklich gross ist der Code dort nicht, aber als Anfänger sollte man ein Problem eher in zu viele Teilprobleme/-lösungen zerlegen, als zu viel auf einmal machen zu wollen. Es ist in der Regel einfacher später den Code aus ”zu kleinen” Funktionen in ihren Aufrufer zu integrieren als Funktionen aus einer zu gross geratenen Funktion zu isolieren, insbesondere wenn man damit wenig Erfahrung hat. Zudem neigen manchmal anfangs ”zu kleine” Funktionen zu wachsen wenn man beispielsweise anfängt Fehlerbehandlung hinzuzufügen. Zudem haben Funktionen Namen, die zur Dokumentation und damit zum Verständnis beitragen.
harvey186
User
Beiträge: 20
Registriert: Mittwoch 14. Dezember 2016, 08:20

na gut, dann werd ich mal weiter suchen, viekkeicht finde ich ja irgedwo jemanden, der sowas schonmal gemacht hat und mir hilft.

Danke an alle hier für DIe guten Worte.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Ich hab der Diskussion nur am Rande gefolgt.

Code: Alles auswählen

In [5]: [sentence for sentence in re.split('[.?!]\s*', s) if "Kind" in sentence]
Out[5]:
['Als ihrem kleinen Sohn auch ohne sie die Einreise verweigert wird, beschlie\xc3\x9fen sie, ihn in ein Modellsegelboot mit dem Namen Stadt der Gerechtigkeit zu setzen, in der Hoffnung, das Kind werde gefunden',
 '1916 ist das Kind zu einem Mann herangewachsen']

In [7]: s
Out[7]: 'Im Jahr 1895 wird einem jungen Einwandererpaar auf Ellis Island die Einreise in die USA verweigert, weil beide an der Tuberkulose erkrankt sind. Als ihrem kleinen Sohn auch ohne sie die Einreise verweigert wird, beschlie\xc3\x9fen sie, ihn in ein Modellsegelboot mit dem Namen Stadt der Gerechtigkeit zu setzen, in der Hoffnung, das Kind werde gefunden.\n1916 ist das Kind zu einem Mann herangewachsen. Er nennt sich Peter Lake. Peter wurde von dem Gangsterboss Pearly Soames aufgezogen und verdient sich seinen Lebensunterhalt nun als Einbrecher und Dieb. Als Peter beschlie\xc3\x9ft, Pearlys Bande und sein altes Leben zu verlassen, macht er sich seinen Ziehvater zum w\xc3\xbctenden Gegner und wird von dessen Bande gejagt.'
Nicht sehr effizient, lässt sich auch ohne Regulären-Ausdruck iterativ lösen (und verwirft Satzzeichen, \n werden nicht entfernt etc. pp). Die Aufgabe eignet sich doch prima anständig Python zu lernen, wie lese ich eine Datei ein, wie iteriere ich über die die Datei Satzweise etc.
the more they change the more they stay the same
harvey186
User
Beiträge: 20
Registriert: Mittwoch 14. Dezember 2016, 08:20

@david
Danke, das werd ich morgen mal versuchen zu verstehen und umzusetzen
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Bei welchen konkreten Punkten hängst du fest? Kann es sein, dass du im Grunde nach einer Komplettlösung suchst bzw nach etwas, das du nur noch geringfügig modifizieren musst...? Du gehst inhaltlich ja nicht wirklich auf die Hinweise ein, die man dir gibt. Schade eigentlich.
harvey186
User
Beiträge: 20
Registriert: Mittwoch 14. Dezember 2016, 08:20

@sanfu
Also ich weiß nicht was ich noch ausführlicher schreiben soll. Ich suche eine Möglichkeit, dass der ganze Satz, in dem meine Suchwort steht, ausgegeben wir.
Ich keinen kompletten code. Nur wie man halt das zurücklesen vom gefundenen String machen kann. Bei anderen Programmier sprachen kann man String vorwärts oder rückwärts lesen. Ein code wer natürlich schön, aber ich probiere gerne zum lernen selber aus. Denn meine Devise war schon immer: Learning by doing.
Nachdem ich den Tip mit dem Satzweise abspeichern bekommen habe, versuche ich das zu realisieren, wobei ich daran scheitere, dass nicht Satzweise, sondern Absatzweise in meine Datei geschrieben wird.

Aber vielleicht hilft mir ja der Hinweis von David dabei.
Antworten