【问题标题】:Strip unicode character modifiers去除 unicode 字符修饰符
【发布时间】:2013-06-13 22:36:57
【问题描述】:

在 Python 中从 unicode 字符串中去除字符修饰符的最简单方法是什么?

例如:

A͋͠r͍̞̫̜͌ͦ̈́͐ͅt̼̭͞h́u̡̙̞̘̙̬͖͓rͬͣ̐ͮͥͨ̀͏̣应该成为亚瑟

我尝试了文档,但找不到任何这样做的东西。

【问题讨论】:

    标签: python unicode utf-8


    【解决方案1】:

    试试这个

    import unicodedata
    a = u"STRING GOES HERE" # using an actual string would break stackoverflow's code formatting.
    u"".join( x for x in a if not unicodedata.category(x).startswith("M") )
    

    这将删除所有归类为标记的字符,这是我认为您想要的。一般来说,你可以通过unicodedata.category获取一个字符的类别。

    【讨论】:

    • +1。但最好在这里使用.startswith('M') 而不是'M' in。从 6.1 开始,没有任何类别的“M”子类别,但没有规定将来不能有。
    • @abarnert:所以你是说最好使用将来可能会损坏的东西?
    • @martineau:不,最好使用将来不会损坏的东西。如果添加了M 类别的子类别,它将用于组合标记。如果添加了某个其他类别的新M 子类别,则不会用于组合标记。所以,组合标记的正确规则是cat.startswith('M'),而不是'M' in cat。 (不太可能出现那个,因为他们没有添加任何共享主要类别使用的字母的新子类别,并清空了唯一的现有子类别LC。但是没有什么坏处做正确的事,至少有潜在的好处。)
    • 经过更多研究后,我不确定这是否真的很重要。据我了解,unicode 字符数据库具有由“Xx”形式的单个字符表示的类别和子类别。因此,使用'M' in 将在未来工作,因为子类别将是'm',并且startswith 也将继续工作。 Startswith 更有意义,因为它总是第一个字符;除非类别名称发生根本性变化,否则情况将如此,在这种情况下,您几乎不能指望相同的代码可以工作。
    【解决方案2】:

    您也可以使用regex module 支持的r'\p{M}'

    import regex
    
    def remove_marks(text):
        return regex.sub(ur"\p{M}+", "", text)
    

    例子:

    >>> print s
    A͋͠r͍̞̫̜t̼̭͞h́u̡̙̞̘rͬͣ̐ͮ
    >>> def remove_marks(text):
    ...     return regex.sub(ur"\p{M}+", "", text)
    ...     
    ... 
    >>> print remove_marks(s)
    Arthur
    

    根据您的用例,白名单方法可能会更好,例如,将输入仅限于 ascii 字符:

    >>> s.encode('ascii', 'ignore').decode('ascii')
    u'Arthur'
    

    结果可能取决于文本中使用的 Unicode 规范化。

    【讨论】:

    • 关于规范化的好点——一个或多个标记可能组成一个字母,在这种情况下你会丢失那个字母。但是你可以通过unicoredata.normalize('NFD', s).encode('ascii', 'ignore').decode('ascii') 来解决这个问题。 (您可能想使用 'NFKD' 代替,这取决于您是否希望得到 U+2160 () 之类的东西,如果是的话,是否要将它们视为兼容的等效 U+0049 (I ) 或跳过它们。)
    猜你喜欢
    • 2012-04-16
    • 2012-05-25
    • 2011-01-31
    • 2015-03-27
    • 1970-01-01
    • 2013-11-09
    • 2016-02-20
    • 2015-12-16
    • 2010-12-28
    相关资源
    最近更新 更多