ich habe folgendes Problem - ich möchte einen regulären Ausdruck "unescapen". Unter normalen
Umständen hätte ich ja auf das codecs zurückgegriffen um die Unicodes sauber zu dekodieren aber bedauerlicherweise geht das hier leider nicht so ganz.
Folgenden Helfer habe ich dazu verfasst. Es sei dabei folgendes anzumerken:
- Categorien [\d,\D, ...], Verhaltensmuster [\A, \B, ...] und Referenzen können nicht unescaped werden
- [\a,\f,\n,\r,\t,\v] bleiben erhalten
- alle anderen werden "unescaped" oder entsprechend dekodiert
Was mich stört ist, dass es sich eigentlich um einen UnicodeDecodeError handelt wenn die escape
sequence unvollständig ist und nicht direkt um einen ValueError.
Die Exception UnicodeDecodeError benötigt jedoch einen output-buffer und bei Mapping-Problemen
via "chr" Funktion wird ebenfalls ein UnicodeError geraised. Das kann m.U. verwirrend sein.
Habt Ihr vielleicht eine Idee wie man so etwas implementieren könnte?
Code: Alles auswählen
class UnescapeError(Exception):
pass
import re
_unescapeprog = re.compile(
r'''\\(?:
x[0-9a-fA-F]{,2}|
u[0-9a-fA-F]{,4}|U[0-9a-fA-F]{,8}|
0[0-7]{,2}|[0-9]+|
.|$
)''', re.VERBOSE)
def _unescape(mo):
escape = mo.group()
try:
if escape[1] in "afnrtv":
return escape
elif escape[1] in "ABbDdSsWwZ":
raise UnescapeError(escape)
elif escape[1] == 'x':
if len(escape) != 4:
raise ValueError(
"incomplete escape sequence {:-<04}".format(escape))
return chr(int(escape[2:], 16) & 0xff)
elif escape[1] == 'u':
if len(escape) != 6:
raise ValueError(
"incomplete escape sequence {:-<06}".format(escape))
return chr(int(escape[2:], 16))
elif escape[1] == 'U':
if len(escape) != 10:
raise ValueError(
"incomplete escape sequence {:-<10}".format(escape))
return chr(int(escape[2:], 16))
elif escape[1] == '0':
return chr(int(escape[1:], 8) & 0xff)
# Unicde escape sequence (exactly three octal-digits) *or*
# decimal group reference (sign)
elif escape[1] in "123456789":
if len(escape) != 3 or any(c in "89" for c in escape[1:]):
raise UnescapeError(escape)
return chr(int(escape[1:], 8) & 0xff)
assert len(escape) == 2
return escape[1]
except IndexError:
pass
raise ValueError() # \ at end of string
def unescape(string):
return _unescapeprog.sub(_unescape, string)