71

エスケープ解除する必要のあるエスケープされた文字列がいくつかあります。Pythonでこれを実行したいと思います。

たとえば、Python 2.7では、次のことができます。

>>> "\\123omething special".decode('string-escape')
'Something special'
>>> 

Python 3でそれを行うにはどうすればよいですか?これは機能しません:

>>> b"\\123omething special".decode('string-escape')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
LookupError: unknown encoding: string-escape
>>> 

私の目標は、次のような文字列を取得できるようにすることです。

s\000u\000p\000p\000o\000r\000t\000@\000p\000s\000i\000l\000o\000c\000.\000c\000o\000m\000

そしてそれを次のように変えます:

"support@psiloc.com"

変換を行った後、私が持っている文字列がUTF-8またはUTF-16でエンコードされているかどうかを調べます。

4

6 に答える 6

65

unicode_escape代わりに使用する必要があります:

>>> b"\\123omething special".decode('unicode_escape')

代わりにオブジェクト(python 2.7 unicodeと同等)から始める場合は、最初にバイトにエンコードしてから、でデコードする必要があります。strunicode_escape

最終結果としてバイトが必要な場合は、適切なエンコーディングに再度エンコードする必要があります(.encode('latin1')たとえば、リテラルバイト値を保持する必要がある場合、最初の256個のUnicodeコードポイントは1対1でマップされます)。

あなたの例は、実際にはエスケープ付きのUTF-16データです。からデコードし、バイトを保持するためunicode_escapeに戻ってから、 (BOMなしのUTF 16リトルエンディアン)から:latin1utf-16-le

>>> value = b's\\000u\\000p\\000p\\000o\\000r\\000t\\000@\\000p\\000s\\000i\\000l\\000o\\000c\\000.\\000c\\000o\\000m\\000'
>>> value.decode('unicode_escape').encode('latin1')  # convert to bytes
b's\x00u\x00p\x00p\x00o\x00r\x00t\x00@\x00p\x00s\x00i\x00l\x00o\x00c\x00.\x00c\x00o\x00m\x00'
>>> _.decode('utf-16-le') # decode from UTF-16-LE
'support@psiloc.com'
于 2013-02-11T20:40:08.423 に答える
34

古い「string-escape」コーデックはバイト文字列をバイト文字列にマップし、そのようなコーデックをどうするかについて多くの議論があったため、現在、標準のエンコード/デコードインターフェイスでは利用できません。

しかし、コードはまだC-API(as )にあり、これは文書化されていないとPyBytes_En/DecodeEscapeを介してPythonに公開されています。codecs.escape_encodecodecs.escape_decode

>>> import codecs
>>> codecs.escape_decode(b"ab\\xff")
(b'ab\xff', 6)
>>> codecs.escape_encode(b"ab\xff")
(b'ab\\xff', 3)

これらの関数は、変換されたbytesオブジェクトに加えて、処理されたバイト数を示す数値を返します...後者は無視してかまいません。

>>> value = b's\\000u\\000p\\000p\\000o\\000r\\000t\\000@\\000p\\000s\\000i\\000l\\000o\\000c\\000.\\000c\\000o\\000m\\000'
>>> codecs.escape_decode(value)[0]
b's\x00u\x00p\x00p\x00o\x00r\x00t\x00@\x00p\x00s\x00i\x00l\x00o\x00c\x00.\x00c\x00o\x00m\x00'
于 2014-04-18T09:57:07.660 に答える
21

エスケープシーケンスのstr -to- strデコードが必要な場合は、入力と出力の両方がUnicodeです。

def string_escape(s, encoding='utf-8'):
    return (s.encode('latin1')         # To bytes, required by 'unicode-escape'
             .decode('unicode-escape') # Perform the actual octal-escaping decode
             .encode('latin1')         # 1:1 mapping back to bytes
             .decode(encoding))        # Decode original encoding

テスト:

>>> string_escape('\\123omething special')
'Something special'

>>> string_escape(r's\000u\000p\000p\000o\000r\000t\000@'
                  r'\000p\000s\000i\000l\000o\000c\000.\000c\000o\000m\000',
                  'utf-16-le')
'support@psiloc.com'
于 2019-11-13T02:33:00.560 に答える
3

バイト文字列では使用できませんunicode_escape(つまり、使用できますが、Python 2で使用するのと同じものが常に返されるとは限りませんstring_escape)–注意してください。

この関数はstring_escape、正規表現とカスタム置換ロジックを使用して実装されます。

def unescape(text):
    regex = re.compile(b'\\\\(\\\\|[0-7]{1,3}|x.[0-9a-f]?|[\'"abfnrt]|.|$)')
    def replace(m):
        b = m.group(1)
        if len(b) == 0:
            raise ValueError("Invalid character escape: '\\'.")
        i = b[0]
        if i == 120:
            v = int(b[1:], 16)
        elif 48 <= i <= 55:
            v = int(b, 8)
        elif i == 34: return b'"'
        elif i == 39: return b"'"
        elif i == 92: return b'\\'
        elif i == 97: return b'\a'
        elif i == 98: return b'\b'
        elif i == 102: return b'\f'
        elif i == 110: return b'\n'
        elif i == 114: return b'\r'
        elif i == 116: return b'\t'
        else:
            s = b.decode('ascii')
            raise UnicodeDecodeError(
                'stringescape', text, m.start(), m.end(), "Invalid escape: %r" % s
            )
        return bytes((v, ))
    result = regex.sub(replace, text)
于 2013-03-20T15:59:08.850 に答える
2

py2

"\\123omething special".decode('string-escape')

py3

"\\123omething special".encode('utf-8').decode('unicode-escape')
于 2021-02-22T15:22:19.947 に答える
0

少なくとも私の場合、これは同等でした:

Py2: my_input.decode('string_escape')
Py3: bytes(my_input.decode('unicode_escape'), 'latin1')

convertutils.py:

def string_escape(my_bytes):
    return bytes(my_bytes.decode('unicode_escape'), 'latin1')
于 2019-08-13T15:50:14.020 に答える