Strings fluchten

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
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

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
Diese Nachricht zersört sich in 5 Sekunden selbst ...
BlackJack

Ich denke hier käme man mit relativ einfachen regulären Ausdrücken mit weniger Code aus.
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

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
Diese Nachricht zersört sich in 5 Sekunden selbst ...
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)
Antworten