Регулярное выражение для замены нечувствительных к акценту в Python
В Python 3 я хотел бы иметь возможность использовать re.sub()
"нечувствительным к акценту" способом, как мы можем сделать с re.I
флаг для замены без учета регистра.
Может быть что-то вроде 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, я пью X в X с Хлоей。" (обратите внимание, что на"Chloë"все еще есть акцент) вместо"¿Это 80°C, я пью X в кафе с Хлоей in в реальном питоне.
Я думаю, что такого флага не существует. Так что будет лучшим вариантом для этого? С помощью re.finditer
а также unidecode
на обоих original_text
а также accent_regex
а затем заменить, разделив строку? Или изменив все символы в accent_regex
по их акцентированным вариантам, например: r'[cç][aàâ]f[éèêë]'
?
3 ответа
unidecode
часто упоминается для удаления акцентов в Python, но это также делает нечто большее: он конвертирует '°'
в 'deg'
, который не может быть желаемым результатом.
unicodedata
кажется, достаточно функциональности для удаления акцентов.
С любым рисунком
Этот метод должен работать с любым шаблоном и любым текстом.
Вы можете временно удалить акценты как из текста, так и из регулярных выражений. Информация о матче от 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ë.
Вы можете использовать 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)
Вместо того, чтобы убирать акценты, мне нужно было сохранить акценты в тексте, тогда я использовал следующий код:
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)