Seite 2 von 2

Verfasst: Freitag 1. Februar 2008, 13:00
von Michael Schneider
Hier ist mal mein Ansatz für beliebige Esc-Sequenzen:

Code: Alles auswählen

esc_list = [("\\", "\\\\"), ("\n", r"\n")]

def escape(s, esc_list=esc_list):
    "Escape s with chars from list esc_list where val0=char, val1=esc_sequence"
    for key, esc_seq in esc_list:
        s = s.replace(key, esc_seq)
    return s
        
def unescape(s, esc_list=esc_list):
    "Unescape s with chars from list esc_list where val0=char, val1=esc_sequence"
    chunks = s.split("\\\\")
    for chunk_id in xrange(len(chunks)):
        for key, esc_seq in esc_list:
            if key == "\\": continue
            chunks[chunk_id] = chunks[chunk_id].replace(esc_seq, key)
    return "\\".join(chunks)
    
def test():
    original = "hallo\nwelt\!"
    print "original:         ", list(original), len(original)
    esc = escape(original)
    print "escaped:          ",list(esc), len(esc)
    unesc = unescape(esc)
    print "unescaped (orig.):", list(unesc), len(unesc)
		
if __name__ == "__main__":
    test()
Wenn man sich auf lf beschränkt, kann man die Funktionen natürlich noch verkürzen.

Gruß,
Michel

Verfasst: Freitag 1. Februar 2008, 13:52
von BlackJack
Ich denke hier käme man mit relativ einfachen regulären Ausdrücken mit weniger Code aus.

Verfasst: Montag 4. Februar 2008, 13:18
von Michael Schneider
BlackJack hat geschrieben:Ich denke hier käme man mit relativ einfachen regulären Ausdrücken mit weniger Code aus.
Hi Blackjack,

meine Versuche mit RE scheiterten daran, dass die Backslash- und anderen Escape-Sequenzen in einem Durchgang umgewandelt werden mussten, damit beispielsweise ein beim ersten Durchgang entstandener Backslash nicht mit einem zufällig folgenden 'n' verknüpft wird. Allenfalls könnte man für alle Escape-sequenzen prüfen, ob ihnen eine gerade Anzahl Backslashes vorausgeht.

Wie würdest Du des denn mit RE lösen? Bekommt man die gesamte Konvertierung in einen Durchlauf?

Grüße,
Michel

Verfasst: Montag 4. Februar 2008, 14:37
von BlackJack
Es ist doch nicht weniger Code geworden, weil die regulären Ausdrücke erst aus den Argumenten zusammen gesetzt werden müssen. Es kommt aber in beide Richtungen mit einer einzigen Ersetzung aus:

Code: Alles auswählen

import re

ESCAPE_CHAR = '\\'
ESCAPES = [('\n', 'n')]

def escape(s, escapes=ESCAPES, escape_char=ESCAPE_CHAR):
    to_escape = dict(escapes)
    to_escape[escape_char] = escape_char
    escape_re = re.compile('[%s]' % re.escape(''.join(to_escape.iterkeys())))
    return escape_re.sub(lambda m: escape_char + to_escape[m.group(0)], s)

def unescape(s, escapes=ESCAPES, escape_char=ESCAPE_CHAR):
    from_escape = dict((b, a) for a, b in escapes)
    from_escape[escape_char] = escape_char
    unescape_re = re.compile(re.escape(escape_char) + '(.)')
    return unescape_re.sub(lambda m: from_escape[m.group(1)], s)