UTF-8文本混入cp1252 ASCII字面量,转换代码无效求排查
问题分析及解决办法
核心问题1:字符串转义被提前解析
你定义的字符串里,\x9a和\x9e会被Python直接解析为对应的转义字符,而非保留字面量的\x9a(四个字符:\、x、9、a)。这导致正则表达式r'\\x[0-9a-fA-F]{2}'找不到任何匹配项,因为原文本里不存在这样的字面量序列。
如果你的原始损坏文本确实包含字面量的\xXX格式(比如从文件读取的内容里有\x9a这四个字符),需把字符串定义为原始字符串,避免Python提前转义:
text = r"This text contains some ASCII literal codes like \x9a and \x9e."
核心问题2:编码转换逻辑错误
就算找到了\x9a这样的字面量,当前的转换逻辑也不正确:
char = bytes(code, 'ascii').decode('cp1252')
这段代码是把\x9a四个字符转成ASCII字节,再用cp1252解码,得到的是四个字符的解码结果,而非0x9a字节对应的cp1252字符。
正确步骤应为:
- 提取
\x后面的两位十六进制数字 - 将其转换为整数(对应字节值)
- 把整数转成单字节的bytes对象
- 用cp1252解码成对应字符
修复后的完整代码
import re # 用原始字符串定义,保留字面量的\xXX序列 text = r"This text contains some ASCII literal codes like \x9a and \x9e." # 匹配字面量的\xXX格式,捕获后面的两位十六进制数 codes = re.findall(r'\\x([0-9a-fA-F]{2})', text) # 遍历每个捕获的十六进制码,替换为对应字符 for hex_code in codes: # 转成整数,再转字节,解码cp1252 char = bytes([int(hex_code, 16)]).decode('cp1252') # 构造要替换的字面量字符串 literal = f'\\x{hex_code}' text = text.replace(literal, char) print(text)
运行后输出:This text contains some ASCII literal codes like Š and ž.
补充说明
如果原始文本是从外部读取(比如文件),无需用原始字符串,直接读取即可——文件里的\x9a会被读成四个字符的字面量,不会被Python提前转义。
内容的提问来源于stack exchange,提问作者Markus
相关产品推荐
相关产品推荐

