Регулярное выражение Python, соответствующее свойствам Юникода


Perl и некоторые другие текущие механизмы регулярных выражений поддерживают свойства Юникода, такие как категория, в регулярном выражении. Например, в Perl вы можете использовать \p{Ll} чтобы соответствовать произвольной строчной букве, или p{Zs} для любого разделителя пространства. Я не вижу поддержки этого в 2.x ни 3.x строк Python (с должным сожалением). Кто-нибудь знает о хорошей стратегии, чтобы получить подобный эффект? Доморощенные решения приветствуются.

6   51  

6 ответов:

ты пробовал Ponyguruma, привязка Python к Oniguruma регулярных выражений? В этом двигателе вы можете просто сказать \p{Armenian} чтобы соответствовать армянским символам. \p{Ll} или \p{Zs} работы тоже.

The выражение модуль (альтернатива стандартному re модуль) поддерживает свойства кодовой точки Юникода с \p{} синтаксис.

вы можете кропотливо использовать unicodedata на каждом символе:

import unicodedata

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

говоря о доморощенных решениях, некоторое время назад я написал небольшой программа чтобы сделать именно это-конвертировать категорию Юникода, написанную как \p{...} в диапазон значений, извлеченных из unicode спецификация (В. 5.0.0). Поддерживаются только категории (например.:L,Zs), и ограничивается БМП. Я публикую его здесь, Если кто-то найдет его полезным (хотя этот Oniguruma действительно кажется лучшим вариантом).

пример использование:

>>> from unicode_hack import regex
>>> pattern = regex(r'^\p{Lu}(\p{L}|\p{N}|_)*')
>>> print pattern.match(u'疂_1+2').group(0)
疂_1
>>>

здесь источник. Существует также версия JavaScript, используя те же данные.

вы правы, что классы свойств Unicode не поддерживаются анализатором регулярных выражений Python.

если вы хотите сделать хороший Хак, что было бы в целом полезно, вы можете создать препроцессор, который сканирует строку для таких токенов класса (\p{M} или что угодно) и заменяет их соответствующими наборами символов, так что, например,\p{M} станет [\u0300–\u036F\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F] и \P{M} станет [^\u0300–\u036F\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F].

люди будут вам благодарны. :)

обратите внимание, что в то время как \p{Ll} не имеет эквивалента в регулярных выражениях Python,\p{Zs} должно быть покрыты '(?u)\s'. Элемент (?u), как говорят документы, " сделайте \w, \W, \b, \B, \d, \D, \s и \S зависимыми от базы данных свойств символов Юникода."и \s означает любой символ.