re regexp und einfaches extrahieren von substrings

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
g4borg
User
Beiträge: 16
Registriert: Donnerstag 4. Oktober 2007, 20:38

Freitag 7. März 2008, 11:02

ich versuche eine inifile händisch zu parsen

dabei müsste ich immer pro zeile erkennen ob ein neuer abschnitt beginnt

also
[ABSCHNITT 4] // ein kommentar
A=B

sollte richtig erkannt werden

ich habe nun versucht mit re den substring zu extrahieren, aber bin etwas ratlos, weil unter all den regexp modulen finde ich kein einfaches match wie in java oder javascript, welches mir einfach einen string zurückliefert, wenn er gefunden wird

dann würd ich den substring weiter durchsuchen und die einzelnen bestandteile filtern. a la
s = s.finde("alles vor //")
s = s.strip()
abschnittstyp = s.finde("[* bis space").finde("alles nach [")
abschnittsname = s.finde("*]").finde("alles bis exkl. ]")

wie würdet ihr das machen?
was mir fehlt ist finde() derzeit... :( das ging in js beispielsweise mit s.match(/regexp/)..
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Freitag 7. März 2008, 11:20

g4borg hat geschrieben:ich versuche eine inifile händisch zu parsen
Bevor es irgend wie losgeht: Wieso??? Dafür gibt es doch sehr gute Parser?
g4borg
User
Beiträge: 16
Registriert: Donnerstag 4. Oktober 2007, 20:38

Freitag 7. März 2008, 11:27

*seufzt* das weiss ich, aber allein am code
// Kommentar

solltest sehen, dass es keine standard ini file ist ;)

hab übrigens nun eine funktion erstellt (fehlen noch einige sachen)

Code: Alles auswählen

def find(rx, where):
    r = re.compile(rx)
    s = r.search(where)
    if s:
        return s.group()
    else:
        return None

find("\[\w+\s+\w+\]", "[ASD ASD] // lalala")
liefert '[ASD ASD]'
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Freitag 7. März 2008, 11:56

Willst Du das komplette File parsen? Wenn ja sind da regexps imho keine gute Idee! Die dienen ja eher dazu "kleine" Schnipsel in etwas größerem zu finden.
Auf eine Grammatik kann man ja bei einem ini-File verzichten, außer es hat extrem konfuse Konstrukte. Ansonsten musst Du es doch nur Zeile für Zeile durchgehen und prüfen, ob eine Section, ein Kommentar oder ein Eintrag vorliegt. Auf diese einzelnen Elemente kannst Du dann ggf. einen Regexps anwenden, um die Key, Value-Paare zu bestimmen.

Was ist denn daran außer den Kommentaren nicht Standard? Evtl. kann man die ja ganz einfach rausschneiden und dann normal weitermachen?
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Freitag 7. März 2008, 12:10

Sag einfach mal klar und deutlich, was deine Regexp machen soll.

Und schau dir mal das hier an:
http://docs.python.org/dev/howto/regex.html

Und wenn das nun alles nicht klappen will...nim PyParsing.
Das ist toll bei komplexen Aufgaben mit vielen Ausnahmen.
g4borg
User
Beiträge: 16
Registriert: Donnerstag 4. Oktober 2007, 20:38

Freitag 7. März 2008, 12:37

nein ich parse die file line für line

was ich suchte und zuerst nicht fand war eben ein äquivalent zu match() in js, oder matchstr() in java, welche direkt das gefundene string liefert.
group() scheint da ausreichend zu sein (für mich war python regex etwas komplexer, aber ich hab mich nun durch das tutorial durchgearbeitet und hab den unterschied zu "verienfachten" regexp aufrufen in anderen sprachen nun heraussen)

danke auch für den link. dort ist es schöner formatiert als wo ich es fand.

PyParse dagegen muss ich mir mal ansehen, womöglich auch eine gute lösung, sollte mein versuch zu unperformant sein.

thx!

@inifile: aus anderen gründen (unterkategorien) ist inifile unzureichend. ini files unterstützen nur A=B, wogegen in meiner file A=B, A=C vorkommen kann und damit sozusagen "zwei A's" anlegt. ausserdem gibt es subsektionen und einige erweiterte syntax.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Freitag 7. März 2008, 12:57

Nimm gleich PyParsing.

So wie sich das anhört, sind das schon fortgeschrittene RegExp und entweder du modularisiert das ganz selbst, also mit Konstanten als RegExp.

Code: Alles auswählen

In [33]: WORD = r"\w+"

In [34]: WORD = r"(?P<WORD>\w+)"

In [35]: SENTENCE = r"%s+" % WORD

In [36]: re.findall(SENTENCE, "Meine Oma mag Kartoffeln!", re.UNICODE)
Out[36]: ['Meine', 'Oma', 'mag', 'Kartoffeln']
BlackJack

Freitag 7. März 2008, 13:16

@g4borg: Bei dem Tipp mit PyParsing geht's nicht um Geschwindigkeit, sondern dass man, nachdem man alle Sonderfälle berücksichtigt hat, immer noch versteht was der Code macht.

Das wird bei regulären Ausdrücken schnell unübersichtlich, vor allem wenn man sich da heran tastet und einen Fall nach dem anderen einbaut.

Wenn Du das Format selber in der Hand hast, könntest Du auch einen Blick auf ConfigObj werfen, bevor Du so etwas selber implementierst.
g4borg
User
Beiträge: 16
Registriert: Donnerstag 4. Oktober 2007, 20:38

Freitag 7. März 2008, 16:23

wow, danke, da lernt man immer was dazu!

derzeit ist der parser schon fertig (und sehr schnell, juhu) aber es kommen sicher aufgaben, die noch komplexer sind, da wäre sowas sicher auch nicht schlecht.

fehler fürchte ich weniger, aus gewohnheit denk ich meist sehr viele fälle durch, selbst jene die nie auftreten
aber stimmt, code-readbarkeit leidet schon drunter.

vor allem das word/sentence beispiel is ja cool.
geh ich richtig davon aus dass ?P<Variable> eine wiederholung markiert? muss ich überlesen haben diese möglichkeit.

auhc configobj is super. vor allem wenn ich das teil in neue projekte einbauen will wohl, thx!
Zuletzt geändert von g4borg am Freitag 7. März 2008, 16:32, insgesamt 1-mal geändert.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Freitag 7. März 2008, 16:28

Lies dir mal http://docs.python.org/lib/module-re.html durch, das dürfte deine Fragen klären.
Das '+' kennzeichnet die Wiederholung, das (?P<name>) bennent nur das gefundene, sodass man nacher auf dem Match-Objekt mit match.get('name') darauf zugreifen kann.
Antworten