2013-02-11 34 views
29

Tôi có một số chuỗi thoát mà không cần thoát. Tôi muốn làm điều này bằng Python.làm thế nào để tôi .decode ('string-escape') trong Python3?

Ví dụ, trong python2.7 tôi có thể làm điều này:

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

Làm thế nào để làm điều đó trong Python3? Điều này không làm việc:

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

Mục tiêu của tôi là trở thành abel để có một chuỗi như thế này:

s\000u\000p\000p\000o\000r\000t\[email protected]\000p\000s\000i\000l\000o\000c\000.\000c\000o\000m\000 

Và biến nó thành:

"[email protected]" 

Sau khi tôi làm việc chuyển đổi , Tôi sẽ thăm dò xem chuỗi tôi có được mã hóa bằng UTF-8 hay UTF-16.

+1

Hãy thử điều này:. 'Byte ("\ 123omething đặc biệt", "utf-8") giải mã ("unicode_escape") ' –

+0

Bạn có hoàn toàn chắc chắn đó là những thoát và không byte đen? –

+0

Chúng là các byte chữ!Có một dấu gạch chéo ngược, sau đó là 0, sau đó một 0, sau đó một thứ ba 0 ... Tôi có một chương trình đọc một tập tin nhị phân và kết quả đầu ra thông tin như thế này. Nó xuất ra tệp nhị phân thực sự có trong tệp. Đôi khi nội dung của tập tin được mã hóa UTF-8 và nó chỉ đi qua. Nhưng nếu nó không phải là hợp lệ UTF-8 nó được mã hóa theo cách này. – vy32

Trả lời

28

Bạn sẽ phải sử dụng unicode_escape thay vì:

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

Nếu bạn bắt đầu với một đối tượng str thay vì (tương đương với python 2,7 unicode), bạn sẽ cần phải mã hóa để byte đầu tiên, sau đó giải mã với unicode_escape.

Nếu bạn cần byte làm kết quả cuối cùng, bạn sẽ phải mã hóa lại thành mã hóa phù hợp (ví dụ: .encode('latin1'), nếu bạn cần bảo tồn giá trị byte của byte; 255 mã unicode đầu tiên bản đồ 1-on-1) .

Ví dụ của bạn thực sự là dữ liệu UTF-16 có các lần thoát. Giải mã từ unicode_escape, trở lại latin1 để bảo tồn các byte, sau đó từ utf-16-le (UTF-16 về cuối nhỏ mà không BOM):

>>> value = b's\\000u\\000p\\000p\\000o\\000r\\000t\\[email protected]\\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\[email protected]\x00p\x00s\x00i\x00l\x00o\x00c\x00.\x00c\x00o\x00m\x00' 
>>> _.decode('utf-16-le') # decode from UTF-16-LE 
'[email protected]' 
+0

Điều đó biến đối tượng nhị phân của tôi thành một đối tượng Unicode. Tôi muốn giữ cho nó một đối tượng nhị phân. Có cách nào để làm điều đó không? – vy32

+0

@ vy32: Mã hóa sau khi giải mã? Mã hóa nào bạn mong đợi điều này để phù hợp? ASCII, Latin 1? –

+0

Nó có thể là bất cứ điều gì. Chương trình thăm dò nhiều mã nguồn khác nhau. Nó có thể là ASCII, UTF-8, UTF-16, Latin 1 hoặc hàng chục khả năng khác. – vy32

3

Bạn không thể sử dụng unicode_escape trên dây byte (hay đúng hơn, bạn có thể, nhưng nó doesn Không phải lúc nào cũng trả về cùng một thứ như string_escape trên Python 2) - hãy cẩn thận!

Chức năng này triển khai string_escape sử dụng biểu thức chính quy và logic thay thế tùy chỉnh.

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) 
12

Các cũ "chuỗi thoát" bản đồ giải mã bytestrings để bytestrings, và có được rất nhiều cuộc tranh luận về những gì để làm với các codec như vậy, vì vậy nó không phải là hiện có sẵn thông qua các giao diện mã hóa/giải mã tiêu chuẩn.

NHƯNG, mã vẫn ở đó trong C-API (như PyBytes_En/DecodeEscape), và điều này vẫn tiếp xúc với Python thông qua số codecs.escape_encodecodecs.escape_decode không có giấy tờ.

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

Đối tượng này trả về đối tượng được chuyển đổi bytes, cộng với số cho biết số byte đã được xử lý ... bạn có thể bỏ qua thứ hai.

>>> value = b's\\000u\\000p\\000p\\000o\\000r\\000t\\[email protected]\\000p\\000s\\000i\\000l\\000o\\000c\\000.\\000c\\000o\\000m\\000' 
>>> codecs.escape_decode(value)[0] 
b's\x00u\x00p\x00p\x00o\x00r\x00t\[email protected]\x00p\x00s\x00i\x00l\x00o\x00c\x00.\x00c\x00o\x00m\x00' 
Các vấn đề liên quan