Seite 1 von 1
Durch bestimmte Textsegmente iterrieren
Verfasst: Dienstag 11. Februar 2014, 11:37
von milexy86
Hallo,
gibt es in Python eine Möglichkeit, ohne reg expressions anzuwenden, bestimmte Segmente eines Textes auszuslesen. Eine Textdatei bestehe beispislweise aus folgenden Inhalt:
Code: Alles auswählen
segmentA {
content Aa
content Ab
content Ac
....
}
segmentB {
content Ba
content Bb
content Bc
......
}
segmentC {
content Ca
content Cb
content Cc
......
}
Wie sage ich dem Script jetzt, suche nach einem bestimmten String innerhalb des Textabschnitt das mit "SegmentC {" beginnt und mit "}" endet.
Eine idee?
Danke im vorraus!
Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Dienstag 11. Februar 2014, 11:55
von /me
Laufe über die Zeilen des Textes. Wenn du auf den Marker für den Beginn des Textabschnitts stößt, dann merke dir, dass du ab jetzt im Suchmodus bist. Wenn du auf den Marker für das Ende des Textabschnitts stößt, dann schalte den Suchmodus wieder ab. Das Suchen selber ist ja trivial (if searchtext in line).
Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Freitag 14. Februar 2014, 10:13
von milexy86
Hallo,
danke erstmals, ich habe das script jetzt so aufgebaut:
Code: Alles auswählen
def SearchStuff(lines,sstr):
i=0
while(lines[i]!='}'):
#Suche einen bestimmten String in den lines. Z.b: nach dem String "Ca"
if 'Ca' in lines[i]:
return lines[i]
i+=1
def main(search_str):
f=open('file.txt','r')
lines = f.readlines()
f.close()
for line in lines:
if search_str in line:
index = lines.index(line)
break
lines = lines[index+1:]
print SearchStuff(lines,search_str)
search_str = 'segmentC {'
main(search_str)
Das Problem hierbei ist: Sobald der Parser auf die Linie mit dem String "Ca" stösst, gibt er auch nur diese Linie aus. Im konkreten Beispiel würde das bedeuten (angenommen "segmentC {" wurde erkannt):
Code: Alles auswählen
segment C {
content Ca\something_ABC\something_EFG\
content Ca\something_XYZ\something_UVW\
content Cc\
}
Hierbei gibt er mir nur die Linie: "content Ca\something_ABC\something_EFG\" aus. Ich bräuchte aber auch die untere Linie, da diese auch den String "Ca" enthält.
Eine Idee?
Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Freitag 14. Februar 2014, 10:39
von /me
milexy86 hat geschrieben:Hierbei gibt er mir nur die Linie: "content Ca\something_ABC\something_EFG\" aus. Ich bräuchte aber auch die untere Linie, da diese auch den String "Ca" enthält.
Du beendest die Verarbeitung mit "return" sobald du eine passende Zeile gefunden hast.
Ich würde so etwas vorschlagen:
Code: Alles auswählen
def wanted_lines(fp, search_text, start_marker, end_marker='}'):
wanted = False
for line in fp:
line = line.rstrip() # das könnte man auch noch in einen Generator eine Zeile höher packen
if line == start_marker:
wanted = True
elif line == end_marker:
wanted = False
else:
if wanted and search_text in line:
yield line
def main():
start_text = 'segment C {'
end_text = '}'
search_text = 'Ca'
with open('file.txt', 'r') as fp:
for line in wanted_lines(fp, search_text, start_text, end_text):
print(line)
if __name__ == '__main__':
main()
Dieser Code liest auch nicht die komplette Datei auf einmal in den Speicher sondern arbeitet sie der Reihe nach ab.
Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Freitag 14. Februar 2014, 11:58
von milexy86
Vielen Dank!
Sollte de start_marker auch nicht entsprechend initialisiert werden?
Wenn ich das Script in der konsole ausführe, tut es leider nichts, gibt auch keine syntax fehler :K
Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Freitag 14. Februar 2014, 12:53
von BlackJack
@milexy86: Für `start_marker` wird doch ein Wert übergeben, also verstehe ich die Frage nicht?
Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Freitag 14. Februar 2014, 13:06
von snafu
Hier noch eine Variante, die vorab geschweifte Klammern annimmt und folglich nur den reinen Namen der Section benötigt. Zudem wird bloß der erste Treffer ausgegeben anstatt eines Iterators:
Code: Alles auswählen
TEST_TEXT = """\
segmentA {
content Aa
content Ab
content Ac
....
}
segmentB {
content Ba
content Bb
content Bc
......
}
segmentC {
content Ca
content Cb
content Cc
......
}"""
def search(lines, section_name, text, start_mark='{', end_mark='}'):
inside_section = False
for line in lines:
line = line.strip()
if line.endswith(start_mark):
current_section = line.rstrip(start_mark).strip()
if current_section == section_name:
inside_section = True
elif line == end_mark:
inside_section = False
elif inside_section and text in line:
return line
def main():
lines = TEST_TEXT.splitlines()
print(search(lines, 'segmentC', 'Cb'))
if __name__ == '__main__':
main()
Anstatt einer Liste von Zeilen funktioniert dies natürlich auch mit einem Dateiobjekt.
Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Montag 17. Februar 2014, 08:34
von milexy86
Hallo,
danke für diesen Vorschlag! Eine Dumme Frage:
Was hat sich mit dem TEST_TEXT = """\ in der ersten Zeile auf sich? Ist das so ne Art Marker im Text File das durchsucht wird?
Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Montag 17. Februar 2014, 09:05
von /me
milexy86 hat geschrieben:Hallo,
danke für diesen Vorschlag! Eine Dumme Frage:
Was hat sich mit dem TEST_TEXT = """\ in der ersten Zeile auf sich? Ist das so ne Art Marker im Text File das durchsucht wird?
Nein, das ist der Beginn einer ganz normalen String-Definition. Du kannst mehrzeiligen Text definieren indem du ihn in dreifache Anführungszeichen einschließt. Der Backslash am Ende ist davon unabhängig. Dieser dient dazu Zeilen fortzuführen und verhindert hier eine leere Zeile zu Beginn des Textes (und wäre nicht nötig gewesen).
Code: Alles auswählen
>>> x = """
a
b
c"""
>>> x
'\na\nb\nc'
>>> x = """\
a
b
c"""
>>> x
'a\nb\nc'
Sofern nicht bekannt: Das "\n" in der Ausgabe steht für einen Zeilenumbruch.
Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Montag 17. Februar 2014, 17:07
von Rigoletto
Nur so als Tip, wenn das Textformat nicht festgelegt ist, wechsel ggf. auf XML.
Das
lässt sich echt einfach nutzen.
Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Montag 17. Februar 2014, 17:20
von Hyperion
Oder besser JSON, oder INI, oder YAML, oder...

Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Montag 17. Februar 2014, 17:28
von snafu
Letztlich stellt sich natürlich auch die Frage, wieso das nicht gleich alles komplett in Python oder kmplett in PHP erledigt wird...
Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Dienstag 18. Februar 2014, 10:39
von milexy86
@/me In dem Text file das so aufgebaut ist wie anfangs beschrieben, habe ich nur leserechte...d.h. ich kann dort nicht einfach string definitionen einbauen.
@snafu: Wird doch alles auch nur in python gemacht
Ganz konkret, sieht das text file so aus:
source_code_directories {
- c:\Folder_A\Folder_B\Project_Sources\Algorithm\Algorithm_X
c:\Folder_A\Folder_B\Project_Sources\Algorithm\Algorithm_Y
c:\Folder_A\Folder_B\Project_Sources\Algorithm\Algorithm_Z
c:\Folder_A\Folder_B\Project_Sources\ZZ\Configuration\
c:\Folder_A\Folder_B\Project_Sources\ZZ\Testing
c:\Folder_A\Folder_B\Project_Sources\ZZ\Test_Outputs
c:\Folder_A\Folder_B\Configuration\Gener_Sourcess\X
}
source_code_includes {
- c:\Folder_A\Folder_B\Configuration\Gener_Sourcess\X
c:\Folder_A\Folder_B\Project_Sources\Algorithm\Algorithm_X
c:\Folder_A\Folder_B\Project_Sources\Algorithm\Algorithm_Y
c:\Folder_A\Folder_B\Project_Sources\Algorithm\Algorithm_Z
c:\Folder_A\Folder_B\Project_Sources\Algorithm\Algorithm_F
c:\Folder_A\Folder_B\Project_Sources\FF\Test_Inputs
c:\Folder_A\Folder_B\Project_Sources\FF
c:\Folder_A\Folder_B\Libraries\Includes_A
c:\Folder_A\Folder_B\Libraries\Includes_B
}
Jetzt möchte ich also ganz einfach sagen: Gebe mir alle Zeilen aus die den String "\Algorithm" innerhalb "source_code_includes {" enthalten.
Die Lösung von @/me habe ich ausprobiert. Es gibt keine Syntax fehler, aber das output file bleibt auch leer. :K
Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Dienstag 18. Februar 2014, 10:50
von /me
milexy86 hat geschrieben:@/me In dem Text file das so aufgebaut ist wie anfangs beschrieben, habe ich nur leserechte...d.h. ich kann dort nicht einfach string definitionen einbauen.
Das sollst du ja auch gar nicht. Lerne Code zu lesen und zu verstehen. snafu hat hier ein Beispiel für die mögliche Verarbeitung gegeben. In diesem Beispiel wurde der Text als String definiert und nicht aus einer Datei gelesen. Wenn du den Text aus einer Datei haben möchtest, dann musst du das schon selber passend umsetzen.
Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Dienstag 18. Februar 2014, 10:55
von /me
milexy86 hat geschrieben:Die Lösung von @/me habe ich ausprobiert. Es gibt keine Syntax fehler, aber das output file bleibt auch leer. :K
Wenn ich in meinem Code die passenden Angaben mache, dann funktioniert das problemlos.
Code: Alles auswählen
start_text = 'source_code_includes {'
search_text = '\\Algorithm'
Du hast nicht vielleicht in der Datei noch führende Leerzeichen vor den Zeilen? Lass dir doch die Zeilen bei der Verarbeitung mal ausgeben (vorzugsweise mit print(repr(line)) ) und schau mal wie die Zeile aussieht die eigentlich gefunden werden sollte, aber nicht gefunden wird.
Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Dienstag 18. Februar 2014, 11:45
von snafu
milexy86 hat geschrieben:@snafu: Wird doch alles auch nur in python gemacht
Ups, ich ich bin mit einem anderen Thread durcheinander gekommen...

Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Dienstag 18. Februar 2014, 12:00
von milexy86
Hallo,
ja, es funktioniert jetzt!
Wie kann ich aber einen Tuple an strings suchen, also beispielsweise:
Muss ich im Attribut "search_text" bei der Funktion "wanted_lines" diese Möglichkeit irgendwie explizit angeben?
Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Dienstag 18. Februar 2014, 12:41
von cofi
Passe Zeile 10 (Code von /me) an mit
(und am besten aenderst du `search_text` noch zum Plural)
Die Alternative sind Regular Expressions.
Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Dienstag 18. Februar 2014, 12:42
von /me
milexy86 hat geschrieben:Wie kann ich aber einen Tuple an strings suchen, [...]
Wenn du ein Tupel aus Möglichkeiten definierst, dann musst du überprüfen ob mindestens einer der Einträge in der Zeile zu finden ist. Zuerst nennen wir den Bezeichner mal
search_texts. Das hat zwar keine Auswirkungen auf den Ablauf des Codes, beschreibt den Inhalt aber korrekter.
Um abzufragen ob eine der Möglichkeiten passt kann man
any verwenden.
any erhält als Parameter ein Iterable dessen zurückgelieferte Elemente überprüft werden. Diese Elemente sollten also angeben, ob die Suche zutrifft. Benötigt wird also eine Schleife die alle Elemente von
search_texts durchläuft und für jedes zurückmeldet ob es in
line vorhanden ist. Wenn man das kombiniert gelangt man zu folgendem Code:
Solltest du Verständnisprobleme mit der Zeile haben, dann frag bitte nach. Code nach diesem Muster ist ziemlich elementar beim Umgang mit Python.
Edit: Wenn hier zwei erfahrene Leute den gleichen Code vorschlagen, dann ist das vermutlich korrekt.

Re: Durch bestimmte Textsegmente iterrieren
Verfasst: Dienstag 18. Februar 2014, 15:17
von milexy86
Hallo,
danke euch nochmals für die umfangreiche Unterstützung und die Tipps. Bin jetzt um einiges an Wissen reicher geworden
Die Lösung mit "any" funktioniert.
Ich habe das auch mit regulären ausdrücken gelöst:
Code: Alles auswählen
import re
with open("input_file.txt", "r") as infile, open("output_file.txt", 'w') as outfile:
for result in re.findall('source_code_includes(.*?)\}', infile.read(), re.S):
for line in result.split('\n'):
if re.search('(Algorithm|Libraries)', line):
outfile.write(line + '\n')