2016-10-25 2 views
3

Im пытается создать регулярное выражение, которое фиксирует любое число (целое число, float, с научной записью или нет). Я использую группы, чтобы, если мне нужно что-то обновить, я обновляю только одну строку. Вот что я делаю:Python Regular Expression named groups

intNumber = r"(?P<Integer>-?(0|[1-9]+[0-9]*))" # Integer 
floatNumber = r"(?P<Float>"+intNumber+r"\.[0-9]+)" # Float 
sciNumber = r"(?P<Scientific>"+floatNumber+r"(e|E)(-|\+)?[0-9]+)" # Scientific 
anyNumber = r"(?P<AnyNumber>"+sciNumber+"|(?P=Integer)|(?P=Float))" # Any number 

Проблема заключается в том, что, хотя каждый из регулярных выражений работает сама по себе, когда я объединить их все в anyNumber, используя или (|) она фиксирует только номера научной нотации, а не отдыхать , Что я делаю не так?

Edit: Для уточнения мой вопрос, можно ли иметь динамически генерируемый регулярное выражение (с целью простого единого технического обслуживания пятна в виду), что также является достаточно гибким, чтобы позволить мне использовать его компоненты по отдельности, без проблем как переопределение групп и удобное название групп? Я знаю, что я могу просить слишком много ..

+0

Попробуйте http://ideone.com/fu9eOy –

ответ

0

The (?P=Integer) именованного обратной ссылки что соответствует же тексту (не рекурсивна группа подшаблон!), Как подкреплялся захват группы под названием «Integer». То же самое с (?P=Float). Это означает, что вам нужно использовать сам шаблон, а не обратные ссылки.

Кроме того, вы не можете использовать именованные обратные ссылки, если вы планируете динамически строить динамическое выражение. Использовать не захватывая группы и ваш шаблон здание будет выглядеть

import re 
intNumber = r"-?(?:0|[1-9]+[0-9]*)" # Integer 
floatNumber = intNumber+r"\.[0-9]+" # Float 
sciNumber = floatNumber+r"[eE][-+]?[0-9]+" # Scientific 
anyNumber = r"{0}|{1}|{2}".format(sciNumber,floatNumber,intNumber) # Any number 
print(re.findall(anyNumber, '12 12.34 12.34E-34')) 

См Python demo

+0

Хорошо, спасибо! Но если я также хочу обратиться к intNumber group Integer или группе Float, потому что я буду использовать их отдельно (а не только для создания регулярного выражения anyNumber), тогда мне нужно будет захватить группы. В этом случае было бы здорово, если бы я мог назвать группы захвата. См. Мой вопрос edit :) – capitan

+0

Вы просто не можете использовать две именованные группы с одинаковыми именами в regex 're'. С 'anyNumber', определенным только с вашими шаблонами как' r "{0} | {1} | {2}". Format (sciNumber, floatNumber, intNumber) ', вы получите исключение. Вы можете использовать модуль регулярных выражений PyPi или забыть о таком наименовании глубокого уровня. –

0

я в конечном итоге делает следующее:

intNumber_re = r"(?P<Integer>-?(0|[1-9]+[0-9]*))" # Integer 
floatNumber_re = r"(?P<Float>"+intNumber_re+r"\.[0-9]+)" # Float 
sciNumber_re = r"(?P<Scientific>"+floatNumber_re+r"[eE][-\+]?[0-9]+)" # Scientific 
groupNames_re = r'(\?P<Integer>)|(\?P<Float>)|(\?P<Scientific>)' 
anyNumber_re = r"(?P<AnyNumber>{0}|{1}|{2})".format(re.sub(groupNames_re,'?:',sciNumber_re), 
       re.sub(groupNames_re,'?:',floatNumber_re),re.sub(groupNames_re,'?:',intNumber_re)) # Any number 

Эффективно Я удаляю имена групп (regex для них находится в groupNames_re), когда я создаю anyNumber RE с функциями re.sub(). Это немного уродливо, но оно работает и дает мне гибкость, которую я хочу. Спасибо Wiktor за ваш вклад, я в конечном итоге использовал немного вашего кода :)