2013-02-11 11 views
29

Çıkışsız olması gereken bazı çıkış dizeleri var. Bunu Python'da yapmak isterim.Python3'te .decode ('string-escape') nasıl yapılır?

Örneğin, python2.7 ben bunu yapabilirsiniz:

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

Ben Python3 bunu yapmak nasıl? Bu işe yaramazsa:

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

Ve çevirmek: Ben dönüşüm yaptıktan sonra

"[email protected]" 

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

Amacım böyle bir dize almaya abel olmaktır Sahip olduğum dizenin UTF-8 veya UTF-16'da kodlanmış olup olmadığını göreceğim.

+1

bu deneyin: ("unicode_escape") deşifre ("utf-8", "özel 123omething \") 'bayt' –

+0

o kaçar ve edebi bayt kesinlikle emin misiniz? –

+0

Onlar baytlık baytlardır!Bir ters eğik çizgi var, sonra 0, sonra başka bir 0, sonra üçüncü bir 0 ... Ben bir ikili dosya okur ve böyle bir bilgi çıktılar bir program var. Aslında dosyada bulunan ikiliyi çıkarır. Bazen dosyanın içeriği UTF-8 kodludur ve sadece geçer. Fakat eğer geçerli bir UTF-8 değilse, bu şekilde kodlanır. – vy32

cevap

28

yerine unicode_escape kullanmak gerekecektir:

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

bunun yerine str nesneyle (piton 2.7 unicode eşdeğer) başlamak , o zaman deşifre ilk bayt kodlamak gerekir unicode_escape ile. Eğer sonuç olarak bayt ihtiyaç (literalin bayt değerleri korumak için gerekirse örneğin .encode('latin1') birinci 255 Evrenkodlu ilk 1-on-1 eder)

, bir uygun kodlama tekrar kodlamak gerekecek .

Örneğiniz aslında çıkışlarla birlikte UTF-16 verileridir.

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

Bu ikili nesneyi bir Unicode nesnesine dönüştürür. Bunu ikili bir nesne olarak tutmak istiyorum. Bunu yapmanın herhangi bir yolu var mı? – vy32

+0

@ vy32: Kod çözdikten sonra kodlayın? Hangi kodlamayı sığdırmayı bekliyorsunuz? ASCII, Latin 1? –

+0

Bu bir şey olabilir. Program çeşitli olası kodlamaları problar. ASCII, UTF-8, UTF-16, Latin 1 veya bir düzine diğer olasılıklar olabilir. – vy32

3

Sen bayt dizeleri üzerinde unicode_escape (daha doğrusu kullanamaz yapabilirsiniz, ama o değil: geri latin1 için unicode_escape gelen Decode utf-16-le den (UTF 16 küçük endian BOM olmadan) daha sonra, bayt korumak için Her zaman aynı şeyi string_escape Python 2'de yaptığınız gibi iade edin) - dikkat!

Bu işlev, düzenli bir ifade ve özel değiştirme mantığı kullanarak string_escape uygular.

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

bytestrings eski "dize kaçış" codec'i haritaları bytestrings ve standart şifreleme/şifre çözme arayüzleri üzerinden şu anda mevcut değildir, bu yüzden bu tür codec'leri ile yapmanız gerekenler hakkında bir çok tartışma olmuş.

Ancak, kod (PyBytes_En/DecodeEscape gibi) Cı-API hala var ve bu yine kayıt dışı codecs.escape_encode ve codecs.escape_decode ile Python maruz kalmaktadır.

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

Bu işlevler dönüştürülmüş bytes nesneyi döndürmek, ayrıca çok sayıda bayt işlenmiştir nasıl gösteren bir numara ... sadece ikincisi göz ardı edebilirsiniz. .

>>> 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'