Perl-совместимое регулярное выражение (PCRE) в Python - PullRequest
26 голосов
/ 15 августа 2011

Мне нужно проанализировать некоторые строки на основе PCRE в Python, и я не знаю, как это сделать.

Строки, которые я хочу проанализировать, выглядит следующим образом:

match mysql m/^.\0\0\0\n(4\.[-.\w]+)\0...\0/s p/MySQL/ i/$1/

ВВ этом примере я должен получить следующие элементы:

"m/^.\0\0\0\n(4\.[-.\w]+)\0...\0/s" ; "p/MySQL/" ; "i/$1/"

Единственное, что я нашел в связи с манипулированием PCRE в Python, - это модуль: http://pydoc.org/2.2.3/pcre.html (но написано, что это.так файл ...)

Знаете ли вы, существует ли какой-либо модуль Python для анализа строки такого типа?

Ответы [ 3 ]

64 голосов
/ 15 августа 2011

Будьте особенно осторожны с не-ASCII в Python

Есть некоторые действительно тонкие проблемы с тем, как Python работает или не справляется с не-ASCII в шаблонах и строках.Хуже того, эти различия существенно различаются не только в зависимости от используемой версии Python, но и от того, используется ли у вас «широкая сборка».

В общем, когда вы работаете с Unicode, Python 3 с широкой сборкой работает лучше , а Python 2 с узкой сборкой работает хуже, но все комбинации все еще довольно далекивдали от того, как работают регулярные выражения Perl по отношению к Unicode.Если вы ищете ᴘᴄʀᴇ паттерны в Python, вам, возможно, придется заглянуть немного дальше, чем его старый re модуль.

досадные проблемы с "широкой сборкой", наконец, имеют исправлено раз и навсегда - при условии, что вы используете достаточно продвинутую версию Python.Вот выдержка из примечаний к выпуску v3.3 :

Функциональность

Изменения, внесенные PEP 393 следующие:

  • Python теперь всегда поддерживает весь диапазон кодов Unicode, включая не BMP (т.е. от U + 0000 до U + 10FFFF).Различия между узкими и широкими сборками больше не существует, и теперь Python ведет себя как широкая сборка даже под Windows.
  • Со смертью узких сборок также были устранены проблемы, характерные для узких сборок, например:
    • len() теперь всегда возвращает 1 для не-BMP символов, поэтому len('\U0010FFFF') == 1;
    • суррогатные пары не рекомбинируются в строковых литералах, поэтому '\uDBFF\uDFFF' != '\U0010FFFF';
    • индексирование или разделение не-BMP символов возвращает ожидаемое значение, поэтому '\U0010FFFF'[0] теперь возвращает '\U0010FFFF', а не '\uDBFF';
    • , все остальные функции в стандартной библиотеке теперь правильно обрабатывают кодовые точки не-BMP.
  • Значение sys.maxunicode теперь всегда равно 1114111 (0x10FFFF в шестнадцатеричном формате).Функция PyUnicode_GetMax() по-прежнему возвращает 0xFFFF или 0x10FFFF для обратной совместимости, и ее не следует использовать с новым Unicode API (см. , выпуск 13054 ).
  • The ./configure flag --with-wide-unicode был удален.

Будущее регулярных выражений Python

В отличие от того, что в настоящее время доступно в стандартной библиотеке re дистрибутива Python, Мэтью Барнетта *Модуль 1066 * для Python 2 и Python 3 одинаково намного, намного лучше во всех возможных отношениях и вполне вероятно заменит re в конце концов.Его особая актуальность для вашего вопроса заключается в том, что его regex библиотека гораздо больше ᴘᴄʀᴇ ( т.е. , она гораздо более совместима с Perl ) во всех отношениях, чем re сейчас, что будетупростить перенос регулярных выражений Perl на PythonПоскольку это перезаписываемая версия (как с нуля, а не как в гамбургере :), она была написана с учетом не-ASCII, чего не было re.

Библиотека regexпоэтому гораздо более точно следует (текущим) рекомендациям UTS # 18: Регулярные выражения Unicode в том, как оно подходит к вещам.Она соответствует или превосходит требования Уровня 1 UTS # 18 в большинстве, если не во всех отношениях, для чего вам обычно нужно использовать библиотеку регулярных выражений ICU или сам Perl - или, если вы особенно смелы, новую Java 7обновите его регулярные выражения, поскольку это также соответствует требованиям первого уровня от UTS # 18.

Помимо удовлетворения требований первого уровня, которые абсолютно необходимы для базовой поддержки Unicode, но которые не соответствуют текущей библиотеке re Python, удивительная regex библиотека также соответствуеттребования второго уровня для RL2.5 именованных символов (\N{...})), RL2.2 расширенных кластеров графем (\X) и нового RL2.7 в полных свойствах из редакция 14 UTS # 18 .

Модуль Мэтью regex также выполняет Unicode casefolТак что сопоставление без учета регистра надежно работает на Unicode, , а re - нет.

Следующее больше не верно, потому что regex теперь поддерживает полное регистр Unicode, как Perl и Ruby.

Одно очень крошечное отличие состоит в том, что на данный момент в Perl-нечувствительных к регистру шаблонах используются полные строковые регистры, в то время как в его модуле regex все еще используются простые тематические складки, ориентированные на один символ, но это то, что он рассматривает , На самом деле это очень сложная проблема, которую, кроме Perl, пытается решить только Ruby.

При полном переносе регистра это означает, что (например) "ß" теперь корректно соответствует "SS", "ss", "ſſ", "ſs" (и т. Д.), Если выбрано сопоставление без учета регистра. (По общему признанию это более важно в греческом письме, чем в латинском.)

См. Также слайды или исходный код документа из моего третьего выступления на OSCON2011 , озаглавленного « Перестрелка с поддержкой Unicode: хорошее, плохое и (в основном) уродливое » для общих проблем поддержки Unicode в JavaScript, PHP, Go, Ruby, Python, Java и Perl. Если вы не можете использовать регулярные выражения Perl или, возможно, библиотеку регулярных выражений ICU (которая, увы, не имеет названий перехватов!), То regex для Python Мэтью, вероятно, ваш лучший выстрел.


Nᴏᴛᴀ Bᴇɴᴇ s.ᴠ.ᴘ. (= s'il vous plaît, et mème s'il ne vous plaît pas :) Следующая незапрошенная некоммерческая нереклама была не на самом деле выложено автором библиотеки Python regex. :)

Круто regex Особенности

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

Вот некоторые выдающиеся особенности этого модуля:

  • Пересматриваемая переменная ширина , функция, которая встречается довольно редко в движках регулярных выражений и очень неприятная, когда ее действительно не хочется. Это может быть наиболее часто запрашиваемая функция в регулярных выражениях.
  • Поиск в обратном направлении, поэтому вам не нужно сначала переворачивать строку самостоятельно.
  • Scoped ismx, так что (?i:foo) складывается только для foo, но не в целом, или (?-i:foo), чтобы отключить его только для foo. Вот как Perl работает (или может).
  • Нечеткое соответствие, основанное на расстоянии редактирования (которое также имеют agrep и glimpse Уди Манбера)
  • Неявные кратчайшие и самые длинные отсортированные именованные списки через \L<list> интерполяция
  • Метасимволы, которые соответствуют только началу или только концу слова, а не любой из сторон (\m, \M)
  • Поддержка всех разделителей строк Unicode (Java может сделать это, как и Perl, хотя и с некоторой неохотой, если \R per RL1.6 .
  • Операции с полным набором - объединение, пересечение, разность и симметричная разность - для классов символов в скобках по RL1.3 , что намного проще, чем получить его в Perl.
  • Позволяет для групп повторного захвата, таких как (\w+\s+)+, где вы можете получить все отдельные совпадения первой группы, а не только ее последнее совпадение. (Я полагаю, что C # также может сделать это.)
  • Более простой способ попасть в перекрывающиеся матчи, чем хитрые группы захвата в предвкушении.
  • Начальная и конечная позиции для всех групп для последующих операций срезов / подстрок, во многом аналогично массивам Perl @+ и @-.
  • Оператор сброса ветви через (?|...|...|...|) для сброса нумерации групп в каждой ветви, как это работает в Perl.
  • Можно настроить, чтобы ваш кофе ожидал вас утром.
  • Поддержка более сложных границ слов из RL2.3 .
  • Принимает строки Unicode по умолчанию и полностью поддерживает RL1.2a sо том, что \w, \b, \s, и такая работа на Unicode.
  • Поддержка \X для графем.
  • Поддерживает утверждение точки продолжения \G.
  • Работает корректно для 64-битных сборок (re имеет только 32-битные индексы).
  • Поддерживает многопоточность.

Хорошо, достаточно шумихи. :)

Еще один прекрасный альтернативный движок регулярных выражений

Еще одна последняя альтернатива, на которую стоит обратить внимание, если вы являетесь фанатом регулярных выражений, - это привязки библиотеки Python к удивительной Russ 2x * библиотеки Russ2x . Он также поддерживает Unicode изначально, в том числе простое наложение символов на основе символов, и, в отличие от re, он в особенности обеспечивает как общую категорию Unicode, так и свойства символов сценария Unicode, которые являются двумя ключевыми свойствами, которые вам чаще всего нужны для более простых видов Unicode. обработка.

Хотя RE2 упускает некоторые функции Unicode, такие как \N{...} поддержка именованных символов в ICU, Perl и Python, он обладает чрезвычайно серьезными вычислительными преимуществами, которые делают его движком регулярных выражений всякий раз, когда вы Вы заботитесь об основанных на голоде атаках типа «отказ в обслуживании» через регулярные выражения в веб-запросах и тому подобное. Он управляет этим путем запрета обратных ссылок, что приводит к тому, что регулярное выражение перестает быть регулярным и подвергается риску сверхэкспоненциальных взрывов во времени и пространстве.

Библиотечные привязки для RE2 доступны не только для C / C ++ и Python, но также для Perl и особенно для Go, где планируется очень скоро заменить стандартную библиотеку regex.

4 голосов
/ 15 августа 2011

Вы ищете '(\w/[^/]+/\w*)'.

Используется примерно так:

import re
x = re.compile('(\w/[^/]+/\w*)')
s = 'match mysql m/^.\0\0\0\n(4\.[-.\w]+)\0...\0/s p/MySQL/ i/$1/'
y = x.findall(s)
# y = ['m/^.\x00\x00\x00\n(4\\.[-.\\w]+)\x00...\x00/s', 'p/MySQL/', 'i/$1/']

Найден во время игры с Regex Coach Эди Вейцц , так что благодарякомментарии к вопросу, который заставил меня вспомнить его существование.

2 голосов
/ 18 июля 2013

Поскольку вы хотите запускать регулярные выражения PCRE, а модуль re Python отличается от исходного источника PCRE, вы также можете проверить привязки Python Аркадия Валига для PCRE . Таким образом, у вас будет доступ к нативному PCRE, и вам не нужно будет переводить между различными типами регулярных выражений.

...