unicode_escape
ไม่ทำงานโดยทั่วไป
ปรากฎว่าโซลูชันstring_escape
หรือunicode_escape
วิธีการแก้ปัญหาไม่ทำงานโดยทั่วไป - โดยเฉพาะอย่างยิ่งไม่สามารถใช้งานได้เมื่อมี Unicode จริง
หากคุณสามารถมั่นใจได้ว่าทุกตัวละครที่ไม่ใช่ ASCII จะหนี (และจำอะไรเกิน 128 ตัวอักษรแรกคือไม่ใช่ ASCII) unicode_escape
จะทำสิ่งที่ถูกต้องสำหรับคุณ แต่ถ้ามีอักขระที่ไม่ใช่ ASCII ตามตัวอักษรอยู่แล้วในสตริงของคุณสิ่งต่างๆจะผิดพลาด
unicode_escape
ได้รับการออกแบบมาโดยพื้นฐานเพื่อแปลงไบต์เป็นข้อความ Unicode แต่ในหลาย ๆ ที่ - ตัวอย่างเช่นซอร์สโค้ด Python ข้อมูลต้นทางเป็นข้อความ Unicode อยู่แล้ว
วิธีเดียวที่จะทำงานได้อย่างถูกต้องคือถ้าคุณเข้ารหัสข้อความเป็นไบต์ก่อน UTF-8 เป็นการเข้ารหัสที่เหมาะสมสำหรับข้อความทั้งหมดดังนั้นจึงควรใช้งานได้ใช่ไหม
ตัวอย่างต่อไปนี้อยู่ใน Python 3 เพื่อให้ตัวอักษรสตริงสะอาดขึ้น แต่ปัญหาเดียวกันนี้มีอยู่โดยมีอาการต่างกันเล็กน้อยใน Python 2 และ 3
>>> s = 'naïve \\t test'
>>> print(s.encode('utf-8').decode('unicode_escape'))
naïve test
ดีที่ผิด
วิธีใหม่ที่แนะนำในการใช้ตัวแปลงสัญญาณที่ถอดรหัสข้อความเป็นข้อความคือการโทรcodecs.decode
โดยตรง ที่ช่วย?
>>> import codecs
>>> print(codecs.decode(s, 'unicode_escape'))
naïve test
ไม่ใช่เลย. (นอกจากนี้ข้างต้นเป็น UnicodeError บน Python 2)
unicode_escape
ตัวแปลงสัญญาณแม้จะมีชื่อของมันจะออกมาคิดว่าทุกไบต์ไม่ใช่ ASCII อยู่ใน Latin-1 (ISO-8859-1) การเข้ารหัส ดังนั้นคุณจะต้องทำเช่นนี้:
>>> print(s.encode('latin-1').decode('unicode_escape'))
naïve test
แต่นั่นแย่มาก สิ่งนี้ จำกัด ให้คุณมีอักขระละติน -1 256 ตัวราวกับว่า Unicode ไม่เคยถูกประดิษฐ์ขึ้นมาเลย!
>>> print('Ernő \\t Rubik'.encode('latin-1').decode('unicode_escape'))
UnicodeEncodeError: 'latin-1' codec can't encode character '\u0151'
in position 3: ordinal not in range(256)
การเพิ่มนิพจน์ทั่วไปเพื่อแก้ปัญหา
(น่าแปลกที่ตอนนี้เราไม่มีปัญหาสองข้อ)
สิ่งที่เราต้องทำคือใช้unicode_escape
ตัวถอดรหัสกับสิ่งที่เรามั่นใจว่าเป็นข้อความ ASCII เท่านั้น โดยเฉพาะอย่างยิ่งเราสามารถตรวจสอบให้แน่ใจว่าได้นำไปใช้กับลำดับการหลีกเลี่ยง Python ที่ถูกต้องเท่านั้นซึ่งรับประกันว่าเป็นข้อความ ASCII
แผนคือเราจะค้นหาลำดับการหลบหนีโดยใช้นิพจน์ทั่วไปและใช้ฟังก์ชันเป็นอาร์กิวเมนต์re.sub
เพื่อแทนที่ด้วยค่าที่ไม่ใช้ Escape
import re
import codecs
ESCAPE_SEQUENCE_RE = re.compile(r'''
( \\U........ # 8-digit hex escapes
| \\u.... # 4-digit hex escapes
| \\x.. # 2-digit hex escapes
| \\[0-7]{1,3} # Octal escapes
| \\N\{[^}]+\} # Unicode characters by name
| \\[\\'"abfnrtv] # Single-character escapes
)''', re.UNICODE | re.VERBOSE)
def decode_escapes(s):
def decode_match(match):
return codecs.decode(match.group(0), 'unicode-escape')
return ESCAPE_SEQUENCE_RE.sub(decode_match, s)
และด้วยสิ่งนั้น:
>>> print(decode_escapes('Ernő \\t Rubik'))
Ernő Rubik
'spam'+"eggs"+'''some'''+"""more"""
การประมวลผลเป็นอย่างไร