String in definierte Zeichen und sonstige Zeichen teilen

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.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Samstag 23. Januar 2010, 15:02

Hier noch eine Variante für die, die (so wie ich) keinen Vertrag mit RE haben ...

Code: Alles auswählen

def symbolsplit(parts, symbols):
    if not symbols: return parts
    symbol = symbols.pop()
    for i in xrange(len(parts)):
        parts[i:i+1] = parts[i].partition(symbol)
    return symbolsplit(filter(None,parts), symbols)

symbols = ["~","##","___"]
text = "sdfasf~ fs##safff# sf#afs__# sf___tttrg_"

print symbolsplit([text],symbols)
Benutzeravatar
snafu
User
Beiträge: 5466
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Samstag 23. Januar 2010, 15:39

Nochmal als Funktion:

Code: Alles auswählen

def seperate(delimiters, s):
    expr = '(%s)' % '|'.join(re.escape(d) for d in delimiters)
    return filter(None, re.split(expr, s))
@numerix: In dem speziellen Fall finde ich RE's handlicher.
shcol (Repo | Doc | PyPi)
jerch
User
Beiträge: 1630
Registriert: Mittwoch 4. März 2009, 14:19

Samstag 23. Januar 2010, 18:24

@snafu
Ich nehme mal, das es Dir um die farbige Terminalsache geht.
Hier mal eine einfache Version:

Code: Alles auswählen

import re

ANSI_CODES = {
    '**' :          {1: '\x1b[1m',      0: '\x1b[22m'},
    '__' :          {1: '\x1b[4m',      0: '\x1b[24m'},
    '#red#':        {1: '\x1b[91m',     0: '\x1b[39m'},
    '#bg_blue#':    {1: '\x1b[104m',    0: '\x1b[49m'},
    }

def tokenize(tokens, s):
    return re.split('(%s)'%'|'.join(re.escape(token)
                                        for token in tokens), s)

def parse(tokens, s_tokenized):
    stack = []
    status = dict(((i, 0) for i in tokens))
    for i, j in enumerate(s_tokenized):
        if i%2:
            if status[j]:
                stack.append(tokens[j][0])
                status[j] = 0
            else:
                stack.append(tokens[j][1])
                status[j] = 1
        else:
            stack.append(j)
    for i, j in status.iteritems():
        if j:
            stack.append(tokens[i][0])
    return stack

s = """
Ich bin **fett**, Du bist __unterstrichen__, #red#farbtest#red#
__Ueberlappung **geht__ wohl** #bg_blue#auch#bg_blue#
"""
s_tokenized = tokenize(ANSI_CODES, s)
s_parsed = parse(ANSI_CODES, s_tokenized)
print s_parsed
print 'Kodiert:', ''.join(s_parsed)
print 'Plain:', ''.join(s_tokenized[::2])
Der Parser ist ziemlich dumm, ua. müßtest Du für überlappende Farbbereiche noch Farbstacks mitschleppen und auswerten. Desweiteren fehlen Escapes, falls man doch mal ein Steuertoken als Text haben will.
Interessant wäre auch, wie man das ganze in Windows ohne ansi.sys umsetzen würde (wenn ich mich recht entsinne, müssen dort extra Terminalbefehle abgesetzt werden)
Benutzeravatar
snafu
User
Beiträge: 5466
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Samstag 23. Januar 2010, 19:14

Das ist super. Ich werde das in der Art bei mir einbauen. Übrigens kann man auch für Dictionary-Schlüssel `True` und `False` verwenden. Dann wird's noch etwas klarer. ;)
shcol (Repo | Doc | PyPi)
jerch
User
Beiträge: 1630
Registriert: Mittwoch 4. März 2009, 14:19

Samstag 23. Januar 2010, 19:29

Ja hast Recht, ich wollte es erst über Bitmasken machen, war mir dann aber zu umständlich.
Hier noch eine escape-Funktion:

Code: Alles auswählen

def escape(tokens, s):
    for i in set([t[0] for t in tokens]):
        s = s.replace(i+'@', i)
    return s
print escape(ANSI_CODE, ''.join(s_parsed))
Ist nur eine Quick-and-Dirty-Idee, mit der Du durch Einfügen eines @ in ein Steuertoken nach dem ersten Zeichen dieses escapen kannst.
Kann man alles noch schöner und ausgefeilter machen.
Benutzeravatar
snafu
User
Beiträge: 5466
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Samstag 23. Januar 2010, 20:55

Ich hab's jetzt erstmal auf das reine Tokenizing runtergebrochen. Der Rest folgt später.

Code: Alles auswählen

_TEXT = 0
_SYMBOL = 1

def _tokenize(symbols, s):
    expr = '(%s)' % '|'.join(re.escape(sym) for sym in symbols)
    for i, value in enumerate(re.split(expr, s)):
        if value:
            yield i % 2, value
Soll halt nicht Teil der API sein, daher die Unterstriche.
shcol (Repo | Doc | PyPi)
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Samstag 23. Januar 2010, 21:29

Warum schreibst du das nicht als Generator Expression? Ungetestet:

Code: Alles auswählen

def _tokenize(symbols, s):
    expr = '(%s)' % '|'.join(re.escape(sym) for sym in symbols)
    return ((i % 2, value) for i, value in enumerate(re.split(expr, s)) if value)
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Samstag 23. Januar 2010, 21:29

Hier noch eine Variante für die, die (so wie ich) keinen Vertrag mit RE haben ...
Denn wer den Vertrag eingeht, wird sowieso früher oder später geholt. :D
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Samstag 23. Januar 2010, 23:30

snafu hat geschrieben:@numerix: In dem speziellen Fall finde ich RE's handlicher.
Ja, ganz gewiss sind sie das. Elegant ist meine Lösung nicht.
Benutzeravatar
snafu
User
Beiträge: 5466
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Sonntag 24. Januar 2010, 00:38

derdon hat geschrieben:Warum schreibst du das nicht als Generator Expression?
Weil ich verschachtelte GE's nicht so lesbar finde wie beim "altmodischen" Weg. Momentan versuche ich, solche Konstrukte zu vermeiden. Aber vielleicht ist es auch nur so eine Phase von mir... ^^
shcol (Repo | Doc | PyPi)
Antworten