Seite 1 von 2

Verfasst: Samstag 23. Januar 2010, 15:02
von numerix
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)

Verfasst: Samstag 23. Januar 2010, 15:39
von snafu
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.

Verfasst: Samstag 23. Januar 2010, 18:24
von jerch
@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)

Verfasst: Samstag 23. Januar 2010, 19:14
von snafu
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. ;)

Verfasst: Samstag 23. Januar 2010, 19:29
von jerch
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.

Verfasst: Samstag 23. Januar 2010, 20:55
von snafu
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.

Verfasst: Samstag 23. Januar 2010, 21:29
von derdon
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)

Verfasst: Samstag 23. Januar 2010, 21:29
von str1442
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

Verfasst: Samstag 23. Januar 2010, 23:30
von numerix
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.

Verfasst: Sonntag 24. Januar 2010, 00:38
von snafu
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... ^^