我会为此使用Unicode normalization。
带有类似重音符号和圆点的字符是precomposed Unicode characters。如果你分解它们,你可以获得基本字符加上combining characters 用于重音和点等等。然后你可以删除你不想要的并将字符串重新组合成预先组合的字符。
您可以在 Python 中使用 unicodedata.normalize 执行此操作。具体来说,您需要“NFD”(规范化形式规范分解)规范化形式。这将为您提供字符的规范分解。然后要重新组合字符,您需要“NFC”(规范化形式规范组合)。
我会告诉你我的意思。首先,让我们看一下您上面提供的示例文本的各个代码点:
>>> from pprint import pprint
>>> import unicodedata
>>> text = 'ọmọàbúròẹlẹ́wà'
>>> pprint([unicodedata.name(c) for c in text])
['LATIN SMALL LETTER O WITH DOT BELOW',
'LATIN SMALL LETTER M',
'LATIN SMALL LETTER O WITH DOT BELOW',
'LATIN SMALL LETTER A WITH GRAVE',
'LATIN SMALL LETTER B',
'LATIN SMALL LETTER U WITH ACUTE',
'LATIN SMALL LETTER R',
'LATIN SMALL LETTER O WITH GRAVE',
'LATIN SMALL LETTER E WITH DOT BELOW',
'LATIN SMALL LETTER L',
'LATIN SMALL LETTER E WITH ACUTE',
'COMBINING DOT BELOW',
'LATIN SMALL LETTER W',
'LATIN SMALL LETTER A WITH GRAVE']
如您所见,其中一个字符已经部分分解(带有单独的“COMBINING DOT BELOW”的字符)。现在让我们看看它完全分解:
>>> text = unicodedata.normalize('NFD', text)
>>> pprint([unicodedata.name(c) for c in text])
['LATIN SMALL LETTER O',
'COMBINING DOT BELOW',
'LATIN SMALL LETTER M',
'LATIN SMALL LETTER O',
'COMBINING DOT BELOW',
'LATIN SMALL LETTER A',
'COMBINING GRAVE ACCENT',
'LATIN SMALL LETTER B',
'LATIN SMALL LETTER U',
'COMBINING ACUTE ACCENT',
'LATIN SMALL LETTER R',
'LATIN SMALL LETTER O',
'COMBINING GRAVE ACCENT',
'LATIN SMALL LETTER E',
'COMBINING DOT BELOW',
'LATIN SMALL LETTER L',
'LATIN SMALL LETTER E',
'COMBINING DOT BELOW',
'COMBINING ACUTE ACCENT',
'LATIN SMALL LETTER W',
'LATIN SMALL LETTER A',
'COMBINING GRAVE ACCENT']
现在根据您的要求,听起来您想保留所有拉丁字母(我猜可能还有 ASCII 的其余部分)加上“COMBINING DOT BELOW”代码点,我们可以参考使用文字 '\N{COMBINING DOT BELOW}' 让您的代码更易于阅读。
这是一个示例函数,我认为它可以满足您的需求:
import unicodedata
def remove_accents_but_not_dots(input_text):
# Step 1: Decompose input_text into base letters and combinining characters
decomposed_text = unicodedata.normalize('NFD', input_text)
# Step 2: Filter out the combining characters we don't want
filtered_text = ''
for c in decomposed_text:
if ord(c) <= 0x7f or c == '\N{COMBINING DOT BELOW}':
# Only keep ASCII or "COMBINING DOT BELOW"
filtered_text += c
# Step 3: Re-compose the string into precomposed characters
return unicodedata.normalize('NFC', filtered_text)
(当然,Python 中的字符串连接很慢,但我会把优化留给你。这个例子是为了可读性而写的。)
结果如下:
>>> remove_accents_but_not_dots('ọmọàbúròẹlẹ́wà')
'ọmọaburoẹlẹwa'