Eigene "config" Dateien gescheid parsen.
Verfasst: Sonntag 11. März 2007, 01:23
Edit (Leonidas): Die Diskussion in den Thread "XML/DTD: Kontextfreiheit?" getrennt.
Angenommen, ihr wollt eine xml-ähnliche Struktur durchparsen, die ungefähr so aussieht:
Ihr wollt das so parsen, dann die einzelnen items isoliert werden können, damit später ihre optionale metadaten ausgelesen werden können, der Rest gilt als message und wird ausgegeben oder wie auch immer. Objekte ausserhalb der item-beschränkungen werden schlicht ignoriert. Die tags müssen nicht zwingend einen Zeilenumbruch haben und die metadaten-variablen müssen nicht mit tab eingerückt sein - es kann also auch alles auf einer Zeile stattfinden, eben wie bei html/xml. Letztenendes möchte ich wenn ich alle items habe in einer for schleife all ihre metadaten auslesen und in ein dictionary packen. Dann verpacke ich dieses metadata-dictionary zusammen mit der message in eine classe/objekt item und dann guck ich weiter.
Bisher mache ich das so unter unix-kommandozeile:
$ sed 's;\\;\\\\;g' config-oben | sed 's;\t;\\t;g' | sed 's;$;\\n;g' | tr -d '\n' > config-temp
$ python
Python 2.4.3 (#1, May 18 2006, 07:40:45)
[GCC 3.3.3 (cygwin special)] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> file = open('config-temp', 'r')
>>> pattern = re.compile('<item>.*?</item>', re.I)
>>> items = pattern.findall(file.read())
>>> items
['<item>\\n<metadata>\\n id="int"\\n creation_time="str|$(date -u)|keywords"\\n expiration_time="str|$(date -u)|keywords"\\n starting_time="str|$(date -u)|keywords"\\n priority="high|medium|low"\\n comment="str"\\n assignies="str"\\n title=""\\n custom_key1=""\\n custom_key2=""\\n ...\\n</metadata>\\nmessage1\\n</item>', '<item>\\n<metadata>\\n id="int"\\n creation_time="str|$(date -u)|keywords"\\n expiration_time="str|$(date -u)|keywords"\\n starting_time="str|$(date -u)|keywords"\\n priority="high|medium|low"\\n comment="str"\\n assignies="str"\\n title=""\\n custom_key1=""\\n custom_key2=""\\n ...\\n</metadata>\\nmessage2\\n</item>']
>>> len(items)
2
>>>
Soweit so gut - jetzt habe ich die items. Doch ich finde das scheisse so. Ich will alles in Python implementieren, da grep nur greedy arbeitet auf regex ebene. Ich brauch aber grep und co. eh nicht, aber wie stelle ich das gescheit an unter Python?
Eine weitere Frage nebenbei ist, wie verwendet man in diesem zusammenhang die MULTILINE option der re von python? Wenn ich die unix-kommandozeile nicht eingebe und das config-file normal einlese, stattdessen aber vorher das pattern so compiliere: pattern = re.compile('<item>.*?</item>', re.I | re.M), dann kommt es leider nicht so raus wie gedacht, weil dann findet er gar kein item.
Mit file = open(myfle, 'rb') habe ich es auch bereits versucht, aber er scheint trotzdem nicht über zeilenrand hinaus zu gehen. Wo ist da der denkfehler bei der angabe des re.M? Wieso hilft mir das nicht bei meiner anforderung?
Edit (Leonidas): Die Diskussion in den Thread "XML/DTD: Kontextfreiheit?" getrennt.
Angenommen, ihr wollt eine xml-ähnliche Struktur durchparsen, die ungefähr so aussieht:
Code: Alles auswählen
<item>
<metadata>
id="int"
creation_time="str|$(date -u)|keywords"
expiration_time="str|$(date -u)|keywords"
starting_time="str|$(date -u)|keywords"
priority="high|medium|low"
comment="str"
assignies="str"
title=""
custom_key1=""
custom_key2=""
...
</metadata>
message1
</item>
junk
<item>
<metadata>
id="int"
creation_time="str|$(date -u)|keywords"
expiration_time="str|$(date -u)|keywords"
starting_time="str|$(date -u)|keywords"
priority="high|medium|low"
comment="str"
assignies="str"
title=""
custom_key1=""
custom_key2=""
...
</metadata>
message2
</item>
Bisher mache ich das so unter unix-kommandozeile:
$ sed 's;\\;\\\\;g' config-oben | sed 's;\t;\\t;g' | sed 's;$;\\n;g' | tr -d '\n' > config-temp
$ python
Python 2.4.3 (#1, May 18 2006, 07:40:45)
[GCC 3.3.3 (cygwin special)] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> file = open('config-temp', 'r')
>>> pattern = re.compile('<item>.*?</item>', re.I)
>>> items = pattern.findall(file.read())
>>> items
['<item>\\n<metadata>\\n id="int"\\n creation_time="str|$(date -u)|keywords"\\n expiration_time="str|$(date -u)|keywords"\\n starting_time="str|$(date -u)|keywords"\\n priority="high|medium|low"\\n comment="str"\\n assignies="str"\\n title=""\\n custom_key1=""\\n custom_key2=""\\n ...\\n</metadata>\\nmessage1\\n</item>', '<item>\\n<metadata>\\n id="int"\\n creation_time="str|$(date -u)|keywords"\\n expiration_time="str|$(date -u)|keywords"\\n starting_time="str|$(date -u)|keywords"\\n priority="high|medium|low"\\n comment="str"\\n assignies="str"\\n title=""\\n custom_key1=""\\n custom_key2=""\\n ...\\n</metadata>\\nmessage2\\n</item>']
>>> len(items)
2
>>>
Soweit so gut - jetzt habe ich die items. Doch ich finde das scheisse so. Ich will alles in Python implementieren, da grep nur greedy arbeitet auf regex ebene. Ich brauch aber grep und co. eh nicht, aber wie stelle ich das gescheit an unter Python?
Eine weitere Frage nebenbei ist, wie verwendet man in diesem zusammenhang die MULTILINE option der re von python? Wenn ich die unix-kommandozeile nicht eingebe und das config-file normal einlese, stattdessen aber vorher das pattern so compiliere: pattern = re.compile('<item>.*?</item>', re.I | re.M), dann kommt es leider nicht so raus wie gedacht, weil dann findet er gar kein item.
Mit file = open(myfle, 'rb') habe ich es auch bereits versucht, aber er scheint trotzdem nicht über zeilenrand hinaus zu gehen. Wo ist da der denkfehler bei der angabe des re.M? Wieso hilft mir das nicht bei meiner anforderung?
Edit (Leonidas): Die Diskussion in den Thread "XML/DTD: Kontextfreiheit?" getrennt.