我有这段代码
import chardet, re
content = "Бланк свидетельства о допуске."
print content
print chardet.detect(content)
content = re.sub(u"(?i)[^-0-9a-zа-яё«»\&\;\/\<\>\.,\s\(\)\*:!\?]", "", content)
print content
print chardet.detect(content)
输出
Бланк свидетельства о допуске.
{'confidence': 0.99, 'encoding': 'utf-8'}
� � .
{'confidence': 0.5, 'encoding': 'windows-1252'}
我做错了什么?我如何在re.sub()之后获得uft-8 str? (Python 2.7,# coding: utf-8
,UTF-8文件,IDE Pycharm)。
感谢。
答案 0 :(得分:6)
这就是我想要实现的目标(为了清晰起见,我简化了正则表达式):
#coding=utf8
import re
content = u"Бланк XYZ свидетельства о ???допуске."
content = re.sub(u"(?iu)[^а-яё]", ".", content)
print content.encode('utf8') # Бланк.....свидетельства.о....допуске.
请注意重点:
(?u)
来进行大小写折叠工作。另外,对于严肃的unicode工作,我推荐使用regex模块,它提供了出色且几乎完整的unicode支持。考虑:
# drop everything except Cyrillic and spaces
import regex
content = regex.sub(u'[^\p{Cyrillic}\p{Zs}]', '', content)
虽然documented re.UNICODE
只改变\w
和朋友,但在我的测试中它也会影响案例折叠(re.IGNORECASE
):
Python 2.7.2+ (default, Oct 4 2011, 20:06:09)
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> src = u'Σσ Φφ Γγ'
>>> src
u'\u03a3\u03c3 \u03a6\u03c6 \u0393\u03b3'
>>> re.sub(ur'(?i)[α-ώ]', '-', src)
u'\u03a3- \u03a6- \u0393-'
>>> re.sub(ur'(?iu)[α-ώ]', '-', src)
u'-- -- --'
因此,这是一个未记录的功能或文档问题。
答案 1 :(得分:2)
您的输入是UTF-8:
>>> content
'\xd0\x91\xd0\xbb\xd0\xb0\xd0\xbd\xd0\xba \xd1\x81\xd0\xb2\xd0\xb8\xd0\xb4\xd0\xb5\xd1\x82\xd0\xb5\xd0\xbb\xd1\x8c\xd1\x81\xd1\x82\xd0\xb2\xd0\xb0 \xd0\xbe \xd0\xb4\xd0\xbe\xd0\xbf\xd1\x83\xd1\x81\xd0\xba\xd0\xb5.'
但您使用的是 unicode 正则表达式。表达式直接匹配 UTF-8输入的原始字节。
在所有这些字节中,只有空格,句号和\xbb
字节(作为»
字符)不会被删除。其余的单个字节将被删除,因为它们不属于负字符类[^...]
。
正确使用Unicode(通过解码content
首先解码)工作:
>>> re.sub(u"(?i)[^-0-9a-zа-яё«»\&\;\/\<\>\.,\s\(\)\*:!\?]", "", content.decode('utf8'))
u'\u043b\u0430\u043d\u043a \u0441\u0432\u0438\u0434\u0435\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0430 \u043e \u0434\u043e\u043f\u0443\u0441\u043a\u0435.'
>>> print re.sub(u"(?i)[^-0-9a-zа-яё«»\&\;\/\<\>\.,\s\(\)\*:!\?]", "", content.decode('utf8'))
ланк свидетельства о допуске.
另一种方法是使用正则表达式的原始字节字符串,并匹配字节组合。计算出UTF-8字节和范围有效是非常,非常棘手。您需要完全了解UTF-8 encodes characters to multiple bytes的方式,然后将您的负字符类转换为一组允许通过相同字节组合的正匹配。对于胆小的人来说,这不。