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

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

Ответ 1

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

Ответ 2

Модуль regex (альтернативный стандартному модулю re) поддерживает свойства кодировки Unicode с синтаксисом \p{}.

Ответ 3

Вы можете очень тщательно использовать unicodedata для каждого символа:

import unicodedata

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

Ответ 4

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

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

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

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

Ответ 5

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

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

Люди будут благодарить вас.:)

Ответ 6

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