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

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

6 ответов

Решение

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

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

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

import unicodedata

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

Говоря о собственных решениях, некоторое время назад я написал небольшую программу для этого - преобразовать категорию Unicode, написанную как \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
>>>

Вот источник. Существует также версия 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 зависимыми от базы данных свойств символов Unicode". и \s означает любой пробел.

Другие вопросы по тегам