【问题标题】:how to remove just the accents, but not umlauts from strings in Python如何从 Python 中的字符串中删除重音符号,而不是变音符号
【发布时间】:2017-11-18 11:28:06
【问题描述】:

我正在使用以下代码

import unicodedata
def strip_accents(s):
    return ''.join(c for c in unicodedata.normalize('NFD', s)
              if unicodedata.category(c) != 'Mn')
strip_accents('ewaláièÜÖ')

返回

'ewalaieUO'

但我希望它返回

'ewalaieÜÖ'

有没有比用 str.replace(char_a,char_b) 替换字符更简单的方法? 我怎样才能有效地处理这个问题?

【问题讨论】:

    标签: python string python-unicode


    【解决方案1】:

    让我们从您的测试输入开始:

    In [1]: test
    Out[1]: 'ewaláièÜÖ'
    

    查看规范化时发生了什么:

    In [2]: [x for x in unicodedata.normalize('NFD', test)]
    Out[2]: ['e', 'w', 'a', 'l', 'a', '́', 'i', 'e', '̀', 'U', '̈', 'O', '̈']
    

    这里是每个标准化元素的 unicodedata 类别:

    In [3]: [unicodedata.category(x) for x in unicodedata.normalize('NFD', test)]
    Out[3]: ['Ll', 'Ll', 'Ll', 'Ll', 'Ll', 'Mn', 'Ll', 'Ll', 'Mn', 'Lu', 'Mn', 'Lu', 'Mn']
    

    如您所见,“重音”和“元音变音”都属于Mn 类别。所以你可以用unicodedata.category代替unicodedata.name

    In [4]: [unicodedata.name(x) for x in unicodedata.normalize('NFD', test)]
    Out[4]: ['LATIN SMALL LETTER E',
     'LATIN SMALL LETTER W',
     'LATIN SMALL LETTER A',
     'LATIN SMALL LETTER L',
     'LATIN SMALL LETTER A',
     'COMBINING ACUTE ACCENT',
     'LATIN SMALL LETTER I',
     'LATIN SMALL LETTER E',
     'COMBINING GRAVE ACCENT',
     'LATIN CAPITAL LETTER U',
     'COMBINING DIAERESIS',
     'LATIN CAPITAL LETTER O',
     'COMBINING DIAERESIS']
    

    这里的重音名称是COMBINING ACUTE/GRAVE ACCENT,“变音符号”名称是COMBINING DIAERESIS。所以这是我的建议,如何修复你的代码:

    def strip_accents(s):
        return ''.join(c for c in unicodedata.normalize('NFD', s)
                  if not unicodedata.name(c).endswith('ACCENT')) 
    
    strip_accents(test)
    'ewalaieÜÖ'
    

    您也可以从unicodedata documentation 中读取此模块只是一个可用数据库here 的包装器,因此请查看该数据库中的list of names,以确保它涵盖了您需要的所有情况。

    【讨论】:

    • 对于那些对 java 11+ 解决方案感兴趣的人,我想出了Normalizer.normalize(s, Normalizer.Form.NFKD).replaceAll("((?<![aouAOU])\\p{M})|((?<=[aouAOU])[\\p{M}&&[^\u0308]])", "")。首先,将 unicode 规范化应用于分解形式,以将辅助字符(例如重音符号)与主字符(如“a”)分开。然后,我们删除所有不以 [aouAOU] 开头的辅助字符以及除 \u0308(组合分音符号)以 [aouAOU] 开头的所有辅助字符。可以使用Normalizer.normalize(s, Normalizer.Form.NFKC); 再次组合结果。
    猜你喜欢
    • 2015-08-30
    • 2010-09-19
    • 2012-12-10
    • 1970-01-01
    • 2022-01-03
    • 2011-04-07
    相关资源
    最近更新 更多