在 python 中替换多个字符映射中的字符

In python replacing characters from multiple char maps

我一直未能找到解决此问题的方法,它是针对一些我无能为力的不良平台代码的解决方法。我想呈现 UTF-8 字符串,但如果平台在其支持的字符映射之外接收到字符,则会崩溃。在这里的例子中,我在俄罗斯有德语 Navi 单元 - 支持拉丁文 2 (iso-8859-2) 和西里尔文 (iso-8859-5),但平台在阿拉伯字符上崩溃。所以我想过滤掉所有非德语或俄语的内容。

此代码:

import codecs
import string

if __name__ == '__main__':
    s = u'Ivan Krsti\u0107\u0416'

    print s

    print s.encode ('iso-8859-1', 'replace')
    print s.encode ('iso-8859-5', 'replace').decode('iso-8859-5')
    print s.encode ('iso-8859-2', 'replace').decode('iso-8859-2')

生产

Ivan KrstićЖ 
Ivan Krsti??
Ivan Krsti?Ж
Ivan Krstić?

我的问题是如何组合 'iso-8859-2' 和 'iso-8859-5' 的字符映射以便在过滤后得到第一个结果? (假设我已经将 UTF-8 编码为 un​​icode。)

您可以使用集合生成对任一编解码器有效的所有代码点:

iso_8859_2 = {chr(i).decode('iso-8859-2') for i in xrange(0xff)}
iso_8859_5 = {chr(i).decode('iso-8859-5') for i in xrange(0xff)}
combined = iso_8859_2 | iso_8859_5

然后将其转化为正则表达式:

import re
# escape meta characters
invalid = u''.join(combined).replace('-', r'\-').replace(']', r'\]')
invalid = re.compile(u'([^{}])'.format(invalid))

并将其应用于 Unicode 文本以过滤掉所有超出这些代码点的代码点:

text_using_only_iso_8859_2_or_5 = invalid.sub('', unicodetext)

这将删除任何给定字符集中不是的代码点。

您还可以使用 unicode.translate(),它将代码点(整数)映射到新的代码点,或者None删除字符:

all_of_unicode = set(range(0x10ffff))
iso_8859_2 = {ord(chr(i).decode('iso-8859-2')) for i in xrange(0xff)}
iso_8859_5 = {ord(chr(i).decode('iso-8859-5')) for i in xrange(0xff)}
# map the difference to None values
to_remove = dict.fromkeys(all_of_unicode - iso_8859_2 - iso_8859_5)
text_using_only_iso_8859_2_or_5 = unicodetext.translate(to_remove)