Wo ist hier der Fehler? - & frage zu '' match '' Objekte

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
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

hallo alle zusammen!

Ich bin gerade so am rumspielen und bastel halt so n bissl rum.

Nun habe ich mal etwas gebastelt, um bestimmte Strings in einem Text zu ersetzen.

Der Teil, um den es geht ist dieser:

Code: Alles auswählen

def replace_headers(data, HeaderList):
        for header, level in HeaderList:
            header.replace(header, '<h%d>%s</h%d>' %(level, header[level:len(header)-(level+1)]))
Wenn ich das ganze nun ausführe erhalte ich eine Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "testing.py", line 47, in ?
    HEADLINE_FUNCTION(template, HEADLINE)
  File "testing.py", line 41, in HEADLINE_FUNCTION
    replaced = replace_headers(data, HeaderList)
  File "testing.py", line 38, in replace_headers
    header.replace(header, '<h%d>%s</h%d>' %(level, header[level:len(header)-(level+1)]))
TypeError: not enough arguments for format string
Verstehen tue ich die schon. Aber so richtig verstehen, wo da ein Argument fehlt tue ich nicht.

Könnt ihr mit helfen?

MfG EnTeQuAk
Zuletzt geändert von EnTeQuAk am Sonntag 17. Dezember 2006, 10:52, insgesamt 2-mal geändert.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi,

ganz einfach:
Du willst drei Argumente inserieren: %d, %s und %d übergibst aber nur zwei, nämlich "level" und "header[level:len(header)-(level+1)]". Wie Du an das dritte Argument kommst, mußt Du nun selber herausfinden, bzw. ob Du das überhaupt so willst.

HTH
Christian
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Ach... ich bin ein trottel :) *peinlich*

Danke! Kommt davon, wenn man da so viel noch zwischendrinne stehen hat!

:)

MfG EnTeQuAk
BlackJack

Was soll das der Slice denn eigentlich liefern? Der Sinn erschliesst sich mir nicht ganz:

Code: Alles auswählen

In [17]: for level in xrange(len(header)):
   ....:     header[level:len(header)-(level+1)]
   ....:
Out[17]: ['a', 'b', 'c']
Out[17]: ['b']
Out[17]: []
Out[17]: []
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

So schauts aus, wenns "fertig" ist... es mag verbesserungswürdig sein funktioniert aber:

Code: Alles auswählen

# -*- coding: utf-8 -*-


import re

template = '''ich bin eine =tolle1 Über===schrift=   dasda dada
ich bin auch eine == tolle2 Über===schrift ==  dasd a
na und ich bin auch eine === tolle3 Über===schrift ===  dasda 
und ich bin ==== keine Überschrift mehr da vier mal = ====
und noch ne === dreier ueberschrift === 
======== test ? ===========
'''

# defines Regex-Syntax
HEADLINE = re.compile(r'(={1,3}\s*.*={1,3})')

def HEADLINE_FUNCTION(data, regex):
    #print regex.findall(data) # testeweise
    def getHeaderList(data, regex):
        HeaderList = []
        for string in regex.findall(data):
            if string.startswith(r'====') and string.endswith(r'===='):
                # hiermit fische ich alles heraus, was laenger als drei mal = ist
                continue
            elif string.startswith(r'===') and string.endswith(r'==='):
                HeaderList.append((string, 3))
                
            elif string.startswith(r'==') and string.endswith(r'=='):
                HeaderList.append((string, 2))
                
            elif string.startswith(r'=') and string.endswith(r'='):
                HeaderList.append((string, 1))
            
            else:
                # don't say never :D
                continue
        return HeaderList
    
    def replace_headers(data, HeaderList):
        count = 0
        for header, level in HeaderList:
            tmp_data = data.replace(header, '<h%d>%s</h%d>' %(level, header[level:len(header)-(level)], level))
            print tmp_data
            data = tmp_data
            count +=1
        return data
                
    HeaderList = getHeaderList(data, regex)
    print 'HeaderList: \n%s\n' % HeaderList
    print 'Ausgangstemplate: \n%s' % template
    data = replace_headers(data, HeaderList)
    print 'Fertige Header: \n\n%s' % data
            

if __name__ == '__main__':
    HEADLINE_FUNCTION(template, HEADLINE)
edit: kleinen Fehler weggemacht... er hat zu viel abgeschnitten


Ausgabe wäre dann folgende:

Code: Alles auswählen

ente@Proggi-PC:~/Desktop/daucms$ python testing.py
HeaderList: 
[('=tolle1 \xc3\x9cber===schrift=', 1), ('== tolle2 \xc3\x9cber===schrift ==', 2), ('=== tolle3 \xc3\x9cber===schrift ===', 3), ('=== dreier ueberschrift ===', 3)]

Ausgangstemplate: 
ich bin eine =tolle1 Über===schrift=   dasda dada
ich bin auch eine == tolle2 Über===schrift ==  dasd a
na und ich bin auch eine === tolle3 Über===schrift ===  dasda 
und ich bin ==== keine Überschrift mehr da vier mal = ====
und noch ne === dreier ueberschrift === 
======== test ? ===========

Fertige Header: 

ich bin eine <h1>tolle1 Über===schrift</h1>   dasda dada
ich bin auch eine <h2> tolle2 Über===schrift </h2>  dasd a
na und ich bin auch eine <h3> tolle3 Über===schrift </h3>  dasda 
und ich bin ==== keine Überschrift mehr da vier mal = ====
und noch ne <h3> dreier ueberschrift </h3> 
======== test ? ===========
Ich denke, das das reicht um zu erklären, wofür ich das benötige :)

Ist halt erstmal nur rumgespiele...

MfG EnTeQuAk
BlackJack

Du kannst bei Slices auch negative Werte angeben. Folgendes ist äquivalent:

Code: Alles auswählen

seq[level:len(seq)-level] == seq[level:-level]
Deinen Quelltext kann man etwas kürzen wenn man das Erkennen von gleichlangen '='-Markierungen vor und hinter der Überschrift schon im regulären Ausdruck erledigt:

Code: Alles auswählen

HEADLINE = re.compile(r'(=+)(\s*.*)(\1)')

def HEADLINE_FUNCTION(data, regex): 
    def getHeaderList(data, regex): 
        HeaderList = [] 
        for match in regex.findall(data):
            level = len(match[0])
            if level <= 3:
                HeaderList.append((match[1], level))
        return HeaderList 
    
    def replace_headers(data, HeaderList): 
        for header, level in HeaderList:
            markup = '=' * level
            data = data.replace(markup + header + markup,
                                '<h%d>%s</h%d>' % (level, header, level))
        return data
Noch etwas übersichtlicher wird es wenn Du gleich die Ersetzungsmethode von regulären Ausdrücken benutzt. Da kannst Du anstelle eines Ersetzungsmusters auch eine Funktion angeben, die das `match`-Objekt bekommt und die Zeichenkette liefert, die stattdessen eingesetzt werden soll.
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Nun habe ich letzteres auch endlich verstanden :)

Jedoch habe ich nun evtl. ein rein Logisches Problem.

Ich habe nun ein Match Objekt. Wie kann ich nun daraus die Zeichenkette liefern. Welche Funktion aktzeptiert Match Objete - wie kann ich den Match ausliefern bzw. was kann man mit denen so alles machen?

Ich finde nicht mal in meinem Buch gute Beispiele. Könntet ihr mir eventuell ein paar geben?

Herzlichen Dank!


MFG EnTeQuAk
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Siehe http://docs.python.org/lib/match-objects.html

Den gesamten "gematchten" Text bekommst du mit match.group(), einzelne Subgruppen mit match.group(x).
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
BlackJack

EnTeQuAk hat geschrieben:Ich habe nun ein Match Objekt. Wie kann ich nun daraus die Zeichenkette liefern. Welche Funktion aktzeptiert Match Objete - wie kann ich den Match ausliefern bzw. was kann man mit denen so alles machen?
Die Funktion musst Du selbst schreiben. Für jeden Treffer bekommt die das `match`-Objekt und kann damit alles machen was so in der Doku steht. Also zum Beispiel auf die einzelnen Gruppen mit der `group()`-Methode zugreifen. Die Funktion muss eine Zeichenkette zurückliefern die dann anstelle der "gematchten" Zeichenkette eingesetzt wird.
Ich finde nicht mal in meinem Buch gute Beispiele. Könntet ihr mir eventuell ein paar geben?
Gleich ein paar? :-)

Man kann das immer anwenden, wenn man beim suchen und ersetzen mittels regulärer Ausdrücke nicht einfach nur Text durch anderen, mehr oder weniger statischen Text, ersetzen will, sondern den gefundenen Text durch etwas berechnetes ersetzen möchte. Simples Beispiel: man möchte alle Hexadezimalzahlen in einem Text durch eine entsprechende Dezimaldarstellung ersetzen. Hexadezimalzahlen werden im Beispiel durch ein führendes '0x' oder ein '$' gekennzeichnet:

Code: Alles auswählen

import re

def main():
    test = 'spam 0x123def, $EA31 eggs'
    
    hex_re = re.compile(r'(0x|\$)(?P<digits>[0-9a-fA-F]+)')
    
    def convert(match):
        return str(int(match.group('digits'), 16))
    
    print hex_re.sub(convert, test)
Dein Überschriftenersetzen kann man dann so lösen:

Code: Alles auswählen

HEADLINE = re.compile(r'(=+)(\s*.*)(\1)')

def HEADLINE_FUNCTION(data, regex):
    def replace_header(match):
        level = len(match.group(1))
        if level > 3:
            return match.group(0)
        else:
            return '<h%d>%s</h%d>' % (level, match.group(2), level)
    
    print 'Ausgangstemplate: \n%s' % template
    data = HEADLINE.sub(replace_header, template)
    print 'Fertige Header: \n\n%s' % data
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Ahhh :) an die '' grou() '' Funktion hab ich gar net mehr gedacht :D


Herzlichen Dank, für das Beispiel! :D

Nun funktioniert auch endlich alles ;)


MfG EnTeQuAk
Antworten