Erste Schritte mit Regular Expressions

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
CrzDivi
User
Beiträge: 5
Registriert: Dienstag 10. Juni 2008, 08:04

Hallo,

steige gerade in Python ein und es fängt sogar an Spass zu machen. :o)

Versuche mich gerade an einem kleinen Converter, es sollen Dateien von DokuWiki in HTML umgewandelt werden, villeicht später auch wieder zurück.

Für den, der es nicht kennt, die Formatierung von Dokuwiki

Code: Alles auswählen

====== Ueberschrift 1======
===== Ueberschrift 2=====
==== Ueberschrift 3====
=== Ueberschrift 4===
== Ueberschrift 5 ==

  * Eine
  * Aufzählung

  - Mit
  - Nummerierung

|Eine|Tabelle|
| | |
| | |
Ich wollte jetzt die ====== Ueberschrift 1====== per Regular Expression in <h1>Ueberschrift 1</h1> umwandeln.
Probier da schon eine Weile rum. Irgendwie wird das aber nicht. Komme ich überhaupt mit den Reg. Exp. weiter, oder muss das alles von hand coden?


Dann villeicht, nochmal ob mein Ansatz überhaupt richtig ist.

clhandler kümmert sich um die Kommandozeile
Aufgerufen wird das ganze mit

dokuwiki2html -v -f dokuwikidatei

Code: Alles auswählen

import os
from re import *

from about import about
from clhandler import clh

class MainApp (object) :
    def __init__(self):
        self.clh = clh('dokuwiki2html.py')
        self.about = about()

        if self.clh.opt.verbose : print self.about.getAppVersion()

        if self.clh.opt.file > '': # check if .file is empty
            if os.path.exists(self.clh.opt.file ): # check if file exists
                
                if self.clh.opt.verbose : print self.clh.opt.file 
                dkw_file = open(self.clh.opt.file,'r')
                
                dkw_text = dkw_file.read()
                dkw_file.close

                if self.clh.opt.verbose:
                    print "DKWFile Content:"
                    print dkw_text

                rexp_list = (("(======)(======)","(=====).(=====)"),
                             ("<h1>.</h1>",'<h2>.<h2>'))

                html_text = dkw_text
                
                for i in range(len(rexp_list[0])):
                    rexp=compile(rexp_list[0][i])

                    if self.clh.opt.verbose: print i, rexp_list[0][i], rexp_list[1][i]

                    html_text = rexp.sub(rexp_list[1][i],html_text)                  
                    

                if self.clh.opt.verbose: print html_text

                html_file = open(self.clh.opt.file + '.html','w')
                html_file.write(str(html_text))
                html_file.close
                
            else : print self.clh.opt.file, "Datei nicht vorhanden"
        elif self.clh.opt.verbose : print "Keine Datei angegeben"

dokuwiki2html = MainApp()
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

CrzDivi hat geschrieben:Komme ich überhaupt mit den Reg. Exp. weiter, oder muss das alles von hand coden?
Ich würde sagen, dass du mit regulären Ausdrücken vor allem bei verschachtelten Dingen nicht weit kommst. Ich würde da wohl eher einen Parser verwenden.

Schau dir mal Mokuwiki an, das ist ein Parser für Dokuwiki-Syntax, der es dann für MoinMoin aufbereitet.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
CrzDivi
User
Beiträge: 5
Registriert: Dienstag 10. Juni 2008, 08:04

danke. hmm, hatte sowas schon befürchtet.

dann werd ich mal den code von Mokuwiki und vom DokuWiki genauer anschauen und dann hoffentlich zu einer sauberen eigenen Lösung kommen.
BlackJack

@CrzDivi: Das Programm kommt übrigens prima ohne eine Klasse aus, die einfach nur eine verkleidete Main-Funktion ist.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Die gezeigte Syntax ist einfach genug, um sie mit regulären Ausdrücken zu bearbeiten. Ich sehe da nichts, was zählen oder verschachteln müsste - etwas, das reguläre Ausdrücke nicht können sondern wo man einen rekursiven Parser bräuchte.

Die Überschriften könnte man Zeile für Zeile so umwandeln:

Code: Alles auswählen

import re

line = re.sub("^======(.*)======$", "<h1>\\1</h1>", line)
Die Tabellen werden etwas komplizierter, hier würde ich empfehlen, zwei Ersetzungen zu schachteln

Code: Alles auswählen

def r(m):
  return "<table><tr><td>" + re.sub("\\|", "</td><td>", m.group(1)) + "</td></tr></table>"

line = re.sub("^\\|(.*)\\|$", r, line)
In einem späteren Schritt muss man dann aus einem aus allen Zeilen zusammengesetzten String noch alle aneinandergrenzenden "</table><table>" entfernen.

Natürlich könnte man auch einen Parser verwenden, dies wäre eine mögliche Grammatik:

Code: Alles auswählen

document = {heading | table | enumeration | paragraph | lineend}
heading = (h1 | h2 | ...) lineend
h1 = "======" text "======"
h2 = "=====" text "====="
table = trow {trow}
trow = "|" text {"|" text} "|" lineend
enumeration = eitem {eitem}
eitem = "  * " text lineend {"    " text lineend}
paragraph = text lineend { text lineend}
text = <kein leerzeichen oder "|" oder "=" oder "\n"> {<kein "\n">}
lineend = "\n"
Diese Grammatik schachtelt nicht Aufzählungen und erlaubt auch keine Aufzählungen oder Überschriften in Tabellen. Könnte man aber entsprechend erweitern, denke ich.

Stefan
Antworten