python 中重音不敏感替换的正则表达式

Regex for accent insensitive replacement in python

在 Python 3 中,我希望能够以 "accent-insensitive" 的方式使用 re.sub(),就像我们可以使用 re.I 标志来处理 case -不敏感的替换。

可能类似于 re.IGNOREACCENTS 标志:

original_text = "¿It's 80°C, I'm drinking a café in a cafe with Chloë。"
accent_regex = r'a café'
re.sub(accent_regex, 'X', original_text, flags=re.IGNOREACCENTS)

这会导致“¿80°C,我正在和 Chloë 在 X 中喝 X。”(请注意 "Chloë" 上仍有重音)而不是“¿80°C,我和 Chloë 在咖啡馆喝 X。" 真实 python.

我认为不存在这样的标志。那么这样做的最佳选择是什么?在 original_textaccent_regex 上使用 re.finditerunidecode 然后通过拆分字符串替换?或者通过重音变体修改 accent_regex 中的所有字符,例如:r'[cç][aàâ]f[éèêë]'?

您可以使用 Unidecode:

$ pip install unidecode

在你的程序中:

from unidecode import unidecode

original_text = "I'm drinking a café in a cafe."
unidecoded_text = unidecode(original_text)
regex = r'cafe'
re.sub(regex, 'X', unidecoded_text)

unidecode 经常被提及用于去除 Python 中的重音符号,但它的作用还不止于此:它将 '°' 转换为 'deg',这可能不是所需的输出。

unicodedata seems to have enough functionality to remove accents.

任意模式

此方法适用于任何图案和任何文本。

您可以暂时删除文本和正则表达式模式中的重音符号。 re.finditer()(开始和结束索引)中的匹配信息可用于修改原始重音文本。

请注意,必须反转匹配才能不修改以下索引。

import re
import unicodedata

original_text = "I'm drinking a 80° café in a cafe with Chloë, François Déporte and Francois Deporte."

accented_pattern = r'a café|François Déporte'

def remove_accents(s):
    return ''.join((c for c in unicodedata.normalize('NFD', s) if unicodedata.category(c) != 'Mn'))

print(remove_accents('äöüßéèiìììíàáç'))
# aoußeeiiiiiaac

pattern = re.compile(remove_accents(accented_pattern))

modified_text = original_text
matches = list(re.finditer(pattern, remove_accents(original_text)))

for match in matches[::-1]:
    modified_text = modified_text[:match.start()] + 'X' + modified_text[match.end():]

print(modified_text)
# I'm drinking a 80° café in X with Chloë, X and X.

如果模式是一个词或一组词

你可以:

  • 删除模式词中的重音并将它们保存在一组中以便快速查找
  • 使用 \w+
  • 查找文本中的每个单词
  • 删除单词的重音:
    • 如果匹配,替换为X
    • 如果不匹配,请保持原样

import re
from unidecode import unidecode

original_text = "I'm drinking a café in a cafe with Chloë."

def remove_accents(string):
    return unidecode(string)

accented_words = ['café', 'français']

words_to_remove = set(remove_accents(word) for word in accented_words)

def remove_words(matchobj):
    word = matchobj.group(0)
    if remove_accents(word) in words_to_remove:
        return 'X'
    else:
        return word

print(re.sub('\w+', remove_words, original_text))
# I'm drinking a X in a X with Chloë.

我需要保留文本的重音,而不是删除重音,然后我使用了以下代码:

accents_dic = {
'A': '(A|Á|À|Â|Ã)',
'E': '(E|É|È)',
'I': '(I|Í|Ï)',
'O': '(O|Ó|Ô|Õ|Ö)',
'U': '(U|Ú|Ü)',
'C': '(C|Ç)'
}
def define_regex_name(name):
    for i, j in accents_dic.items():
        name = re.sub(i,j,name)
    return re.compile(name, re.IGNORECASE)