komplexe regexp, einfacher möglich?

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
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

Die folgende Regexp matcht alle Headlines von h1 bis h5 (wobei h1 = '=' und h5 = '=====').
Syntax für erfolgreichen match:

Code: Alles auswählen

= Ich bin ein h1 = 
 == Ich bin ein h2 mit whitespaces davor und danach ==  
Der Code:

Code: Alles auswählen

import re

rawstr = r"""^\s*(?P<level>={1,5})(?P<inhalt>(?!=).+(?<!=))(?P=level)\s*$"""
matchstr = """= 342 =
== asdfd =
 ==fs  df===			  
 === asd ===  		
 == asd==asd ==   		"""

# method 2: using search function (w/ external flags)
match_obj = re.search(rawstr, matchstr,  re.MULTILINE)

# Retrieve group(s) by name
level = match_obj.group('level')
inhalt = match_obj.group('inhalt')
print level,inhalt
Kann ich die Regex noch etwas besser machen (performance, lesbarkeit etc...)
Der Sinn davon ist diese Regex als lexer.match für Tekisuto zu verwende :)
Funktioniert bis jetzt gut, Hut ab @blackbird für diesen genialen Parser!

MfG apollo13

EDIT:// Hmm, kA wie ich da noch die anderen matches anzeigen kann (ist nur aus Kodos rauskopiert. Nur den Testcode, nicht die Regex, die ist von mir)
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Du weißt aber, das Tekisuto noch kein bisschen released wurde, ja?

Ansonsten für verschiedene Regular Expressions kannst du mal hier schauen:

http://daucms.de/trac/browser/daucms/ut ... er.py#L136

vielleicht hilft dir das ein wenig weiter :)


Übrigens ist Tekisuto kein Parser sondern ist (oder soll werden) ein Framework, um sich selber Parser zu generieren. Tekisuto übernimmt zZ nur die Rolle eines Lexers.
(sollte ich falsch liegen blackbird, sag bescheid ;) )


MfG EnTeQuAk
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

Mein Fehler, meinte natürlich lexer.
Nicht fertig und dennoch sehr gut :)

achja deine headline regex bekommt kleine Probleme mit sowas:
=== asd ====
der content-match wäre dann 'asd ='. Um das zu verhinder ist meine ja so komplex :)

Nachdem Tekisuto ja so perfekt lext, schaut mein Parser (oder was auch immer) nur mehr so aus:

Code: Alles auswählen

def wikify(text):
    """
        Parses the input and returns the new string
    """
    mein_rep = {
    'wiki/italic/start':'<i>',
    'wiki/italic/end':'</i>',
    # snipp
    'wiki/text':(lambda x: x),
    'wiki/heading':(lambda x: '<h%s>%s</h%s>' % (x['level'],x['inhalt'],x['level']))
    }
    erg = ''
    for token in WikiLexer(text):
        if (mein_rep.has_key(token.name) and callable(mein_rep[token.name])):
            erg = erg + mein_rep[token.name](token.data)
        elif mein_rep.has_key(token.name):
            erg = erg + mein_rep[token.name]
    return erg
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

achja deine headline regex bekommt kleine Probleme mit sowas:
=== asd ====
der content-match wäre dann 'asd ='. Um das zu verhinder ist meine ja so komplex
Für mich ist das auch richtig. Denn... willst du das letzte '=' als weiteres '<h1>' ansehen?
Wenn ja, spielst du dem Benutzer eventuell einen starken Streich ;)


Oder verstehe ich dich jetzt falsch?

btw: schau dir ma die Beispiele von Tekisuto an... liegen auch im Trunk :)
da hast du wunderbare Beispiele, wie bestimmte Sachen gelößt werden können.

MfG EnTeQuAk
PmanX
User
Beiträge: 123
Registriert: Donnerstag 25. Januar 2007, 13:50
Wohnort: Germany.BB.LOS
Kontaktdaten:

apollo13 hat geschrieben:Die folgende Regexp matcht alle Headlines von h1 bis h5 (wobei h1 = '=' und h5 = '=====').
...
match_obj = re.search(rawstr, matchstr, re.MULTILINE)
Soll sich die Headline über mehrer Zeilen erstrecken?
re.MULTILINE überdenken.

Code: Alles auswählen

(?P<inhalt>(?!=).+(?<!=))
# wuerde ich so schreiben
(?<inhalt>[^=]+)
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

EnTeQuAk hat geschrieben:
achja deine headline regex bekommt kleine Probleme mit sowas:
=== asd ====
der content-match wäre dann 'asd ='. Um das zu verhinder ist meine ja so komplex
Für mich ist das auch richtig. Denn... willst du das letzte '=' als weiteres '<h1>' ansehen?
Wenn ja, spielst du dem Benutzer eventuell einen starken Streich ;)


Oder verstehe ich dich jetzt falsch?
Nein, das sehe ich durch meine Regex nicht als solches an, es wird einfach nicht als Heading erkannt, sondern nur als === asd ==== ausgegeben.
Wobei es wahrscheinlich etwas zu viel des guten ist, aber dieses Problem hat mir sehr geholfen Regex besser zu verstehn
EnTeQuAk hat geschrieben: btw: schau dir ma die Beispiele von Tekisuto an... liegen auch im Trunk :)
da hast du wunderbare Beispiele, wie bestimmte Sachen gelößt werden können.

MfG EnTeQuAk
Ja die hab ich dafür verwendet, um die Arbeitsweise von Tekisuto zu verstehen :)
PmanX hat geschrieben:
apollo13 hat geschrieben:Die folgende Regexp matcht alle Headlines von h1 bis h5 (wobei h1 = '=' und h5 = '=====').
...
match_obj = re.search(rawstr, matchstr, re.MULTILINE)
Soll sich die Headline über mehrer Zeilen erstrecken?
re.MULTILINE überdenken.
MULTILINE ist in diesem Fall nur für kodos, damit ich einen searchstring mit mehreren Zeilen testen kann.
Siehe http://docs.python.org/lib/node46.html eben damit die Regexp über alle Zeilen läuft und ich Zeile für Zeile auf ein richtiges/falsches heading testen kann, sonst müsste ich immer die erste Zeile abändern und wenn ich in der Regex was falsch mache weiß ich nimmer ob das erste (gelöschte) noch existiert.
PmanX hat geschrieben:

Code: Alles auswählen

(?P<inhalt>(?!=).+(?<!=))
# wuerde ich so schreiben
(?<inhalt>[^=]+)
Nö dann dürfte in der Überschrift kein = Zeichen stehn, ob sich so aufwendig lohnt oder nicht, siehe weiter oben...

MfG apollo13
PmanX
User
Beiträge: 123
Registriert: Donnerstag 25. Januar 2007, 13:50
Wohnort: Germany.BB.LOS
Kontaktdaten:

apollo13 hat geschrieben:MULTILINE ist in diesem Fall nur für kodos, damit ich einen searchstring mit mehreren Zeilen testen kann.
Siehe http://docs.python.org/lib/node46.html eben damit die Regexp über alle Zeilen läuft und ich Zeile für Zeile auf ein richtiges/falsches heading testen kann, sonst müsste ich immer die erste Zeile abändern und wenn ich in der Regex was falsch mache weiß ich nimmer ob das erste (gelöschte) noch existiert.
PmanX hat geschrieben:

Code: Alles auswählen

(?P<inhalt>(?!=).+(?<!=))
# wuerde ich so schreiben
(?<inhalt>[^=]+)
Nö dann dürfte in der Überschrift kein = Zeichen stehn, ob sich so aufwendig lohnt oder nicht, siehe weiter oben...
Ich würde eine RegEx auf einen speziellen Fall erstellen und kann mir nicht vorstellen, dass eine Überschrift über zwei Zeilen laufen soll.
Du läßt doch nur "=" im Zentrum des Strings zu ;) Wenn das sinnvoll ist ..

Gruß P.
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

Sie geht doch nur über eine Zeile, Ich glaube du (oder ich?!) hast multiline nicht ganz verstanden.
Das nimmt doch bei einem String mit mehreren Zeilen jedes newline als ^ bzw $ und somit bekomme ich für jede Zeile einen match oder eben keinen (wie gesagt nur zum Testen ob die RegEx funktioniert. In Tekisuto wird sowieso mit einzelnen Zeilen gearbeitet)
Wäre also so als würde ich die RegEx nach der Reihe mit den einzelnen Zeilen füttern.

Klar ein '=' am Rand des Strings ist etwas kompliziert, ohne Trennung zur headline *gg*
Wenn das sinnvoll ist ..
Learning by doing, wie soll ich sonst das Buch "Mastering Regular Expressions" verstehn ;)
Und nen BBCode/Wiki Parser war das Erste was mir einfiel um solche RegExes auszutesten.
PmanX
User
Beiträge: 123
Registriert: Donnerstag 25. Januar 2007, 13:50
Wohnort: Germany.BB.LOS
Kontaktdaten:

Wenn Du Zeilenweise arbeitest, willst(brauchst) Du Multiline nicht.
Wenn ein String Newlines enthält, will man ihn möglicherweise als Sammlung logische Zeilen betrachten.
_^_ paßt dann auf den Anfang jeder logischen Zeile und _$_ auf das Ende. Nicht mehr, nicht weniger.

Gruß P.
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

Und gerade deshalb verwende ich zum Testen mit Kodos multiline, sonst bekomme ich nur ein match, nämlich das Erste.
Wie dem auch sei es funktioniert wie es soll (ohne Multiline und mit Tekisuto) :)
BlackJack

Also ich finde ``=`` in Überschriften sollte erlaubt sein. Wenn man zum Beispiel einen Text über Python schreibt, liegt eine Überschrift wie "== Der Unterschied zwischen `==` und `is` ==" durchaus im Bereich des Wahrscheinlichen.
PmanX
User
Beiträge: 123
Registriert: Donnerstag 25. Januar 2007, 13:50
Wohnort: Germany.BB.LOS
Kontaktdaten:

Dann würde ich die Syntax derartig einschränken.

Code: Alles auswählen

cre = re.compile(r'(?P<bound>^={2,5})([ ].*?[ ])(?P=bound)$')
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

Könnte man machen, dann wäre das Leerzeichen allerdings zwinged, das würde ich nervig finden...
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Also ich finde ``=`` in Überschriften sollte erlaubt sein. Wenn man zum Beispiel einen Text über Python schreibt, liegt eine Überschrift wie "== Der Unterschied zwischen `==` und `is` ==" durchaus im Bereich des Wahrscheinlichen.
Könnte man mit dem alltbekannten 'escapen' realisieren.

mit folgender Regex könnte man bestimmte Headlines 'escapen' und sie vorm ersetzen fernhalten:

Code: Alles auswählen

cre = re.compile(r'!?(?P<bound>={2,5})(.*)(?P=bound)')
Wobei hier die Bindung an den Satzanfang fehlt...

MfG EnTeQuAk
PmanX
User
Beiträge: 123
Registriert: Donnerstag 25. Januar 2007, 13:50
Wohnort: Germany.BB.LOS
Kontaktdaten:

apollo13 hat geschrieben:Könnte man machen, dann wäre das Leerzeichen allerdings zwinged, das würde ich nervig finden...
Ich würde Wildwuchs nervig finden ;)
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

Hehe jeder wie er meint und so ist es auch gut :)
Antworten