有效地替换坏人物

时间:2011-07-07 11:31:07

标签: python string unicode replace

我经常使用包含以下字符的utf-8文本:

  

\ XC2 \ X99

     

\ XC2 \ X95

     

\ XC2 \ X85

     

这些字符会混淆我使用的其他库,因此需要更换。

有效的方法是什么,而不是:

text.replace('\xc2\x99', ' ').replace('\xc2\x85, '...')

6 个答案:

答案 0 :(得分:32)

总有正则表达式;只列出方括号内的所有违规字符,如下所示:

import re
print re.sub(r'[\xc2\x99]'," ","Hello\xc2There\x99")

打印:'Hello There',不需要的字符替换为空格。

或者,如果每个人都有不同的替换字符:

# remove annoying characters
chars = {
    '\xc2\x82' : ',',        # High code comma
    '\xc2\x84' : ',,',       # High code double comma
    '\xc2\x85' : '...',      # Tripple dot
    '\xc2\x88' : '^',        # High carat
    '\xc2\x91' : '\x27',     # Forward single quote
    '\xc2\x92' : '\x27',     # Reverse single quote
    '\xc2\x93' : '\x22',     # Forward double quote
    '\xc2\x94' : '\x22',     # Reverse double quote
    '\xc2\x95' : ' ',
    '\xc2\x96' : '-',        # High hyphen
    '\xc2\x97' : '--',       # Double hyphen
    '\xc2\x99' : ' ',
    '\xc2\xa0' : ' ',
    '\xc2\xa6' : '|',        # Split vertical bar
    '\xc2\xab' : '<<',       # Double less than
    '\xc2\xbb' : '>>',       # Double greater than
    '\xc2\xbc' : '1/4',      # one quarter
    '\xc2\xbd' : '1/2',      # one half
    '\xc2\xbe' : '3/4',      # three quarters
    '\xca\xbf' : '\x27',     # c-single quote
    '\xcc\xa8' : '',         # modifier - under curve
    '\xcc\xb1' : ''          # modifier - under line
}
def replace_chars(match):
    char = match.group(0)
    return chars[char]
return re.sub('(' + '|'.join(chars.keys()) + ')', replace_chars, text)

答案 1 :(得分:20)

我认为这里存在潜在的问题,调查并解决问题可能是一个好主意,而不仅仅是试图掩盖症状。

\xc2\x95是字符U + 0095的UTF-8编码,它是C1 control character(MESSAGE WAITING)。您的图书馆无法处理它并不奇怪。但问题是,它是如何进入您的数据的?

嗯,一个非常可能的可能是它开始是Windows-1252编码中的字符0x95(BULLET),被错误地解码为U + 0095而不是正确的U + 2022,然后编码为UTF -8。 (日语术语mojibake描述了这种错误。)

如果这是正确的,那么您可以通过将原始字符放回Windows-1252然后再将​​它们正确解码为Unicode来恢复原始字符。 (在这些示例中,我使用的是Python 3.3;这些操作在Python 2中有点不同。)

>>> b'\x95'.decode('windows-1252')
'\u2022'
>>> import unicodedata
>>> unicodedata.name(_)
'BULLET'

如果要对0x80-0x99范围内有效Windows-1252字符的所有字符进行此更正,可以使用此方法:

def restore_windows_1252_characters(s):
    """Replace C1 control characters in the Unicode string s by the
    characters at the corresponding code points in Windows-1252,
    where possible.

    """
    import re
    def to_windows_1252(match):
        try:
            return bytes([ord(match.group(0))]).decode('windows-1252')
        except UnicodeDecodeError:
            # No character at the corresponding code point: remove it.
            return ''
    return re.sub(r'[\u0080-\u0099]', to_windows_1252, s)

例如:

>>> restore_windows_1252_characters('\x95\x99\x85')
'•™…'

答案 2 :(得分:11)

如果要从字符串中删除所有非ASCII字符,可以使用

text.encode("ascii", "ignore")

答案 3 :(得分:2)

import unicodedata

# Convert to unicode
text_to_uncicode = unicode(text, "utf-8")           

# Convert back to ascii
text_fixed = unicodedata.normalize('NFKD',text_to_unicode).encode('ascii','ignore')         

答案 4 :(得分:0)

这不是“Unicode字符” - 感觉更像是一个UTF-8编码的字符串。 (虽然你的前缀应该是\ xC3,而不是大多数字符的\ xC2)。除非您使用COBOL后端进行通信,否则不应该将其丢弃在95%的情况下。你知道,世界并不限于26个字符。

有一个简洁的解释来解释Unicode字符串之间的区别(在python 2中用作Unicode对象,在Python 3中用作字符串:http://www.joelonsoftware.com/articles/Unicode.html - 请为此而阅读。甚至如果你从来没有计划在你的所有应用程序中都有任何非英语的东西,你仍会偶然发现像€或º这样的符号不适合7位ASCII。那篇文章会对你有帮助。

也就是说,您使用的库可能接受Unicode python对象,您可以通过执行以下操作将UTF-8 Python 2字符串转换为unidoce:

var_unicode = var.decode("utf-8")

如果你真的需要100%纯ASCII,替换所有非ASCII字符,在将字符串解码为unicode之后,将其重新编码为ASCII,告诉它忽略不适合的字符charset:

var_ascii = var_unicode.encode("ascii", "replace")

答案 5 :(得分:0)

这些字符不在ASCII库中,这就是您收到错误的原因。 为避免这些错误,您可以在读取文件时执行以下操作。

import codecs   
f = codecs.open('file.txt', 'r',encoding='utf-8')

要了解有关此类错误的更多信息,请浏览this link