Регулярное выражение Python, соответствующее свойствам Юникода - PullRequest
53 голосов
/ 02 декабря 2009

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

Ответы [ 6 ]

57 голосов
/ 30 ноября 2010

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

23 голосов
/ 03 декабря 2009

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

6 голосов
/ 12 ноября 2010

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

import unicodedata

def strip_accents(x):
    return u''.join(c for c in unicodedata.normalize('NFD', x) if unicodedata.category(c) != 'Mn')
5 голосов
/ 04 марта 2012

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

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

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

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

4 голосов
/ 02 декабря 2009

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

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

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

2 голосов
/ 05 декабря 2009

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

...