Регулярное выражение: использование обратной ссылки в совпавших временах {n}?

Я хочу использовать регулярное выражение для соответствия списку строк: 1a, 2aa, 3aaa... где первая цифра в строке обозначает, сколько букв а следует за этой цифрой.

Интуитивно я думаю, что обратная ссылка может помочь, но это неправда.

В Regex мы можем использовать обратную ссылку для сопоставления с ранее захваченным подшаблоном. Например, (.+) \1 соответствует aaa aaa.

Могу ли я использовать обратную ссылку во временах совпадения с шаблоном {n}, {n,m} или {n,}?

Например, \da{\1} в идеале соответствовало бы 3aaa, однако я проверил это с модулем сборки python re, это не работает. Кажется, компилятор понимает \da{\1} как другой литерал:

>>> re.compile('\da{\1}', re.DEBUG)
in
  category category_digit`
literal 97
literal 123
literal 1
literal 125
<_sre.SRE_Pattern object at 0xb7726790>

>>> re.compile('\da{1}', re.DEBUG)`
in
  category category_digit
max_repeat 1 1
  literal 97
<_sre.SRE_Pattern object at 0xb7707820>

Эта функция не реализована модулем или просто потому, что эта функция не может поддерживаться базовым алгоритмом регулярных выражений?


person crsxl    schedule 16.10.2012    source источник
comment
Я не могу навскидку найти место в документации, объясняющее, почему это не разрешено, но я очень сомневаюсь, что это будет поддерживаться. {} - это ожидаемые цифры, а не групповой результат, который вы ему даете, хотя в конечном итоге он возвращает число.   -  person jdotjdot    schedule 16.10.2012
comment
Нет, ты не можешь. Регулярные выражения должны анализировать обычные языки   -  person JBernardo    schedule 16.10.2012
comment
@JBernardo Должен быть ключевым словом. Обычно, когда вы хотите найти шаблоны, которые начинаются и заканчиваются одним и тем же словом, вы должны использовать что-то похожее на ^([a-z]+)(.*)\1$, что, по сути, и пытается выполнить OP, но внутри {} вместо этого.   -  person newfurniturey    schedule 16.10.2012
comment
@newfurniturey Нет, это не так. Количество повторений не может быть выбрано произвольно самим языком.   -  person JBernardo    schedule 16.10.2012
comment
@JBernardo Разве обратная ссылка буквально не повторяет совпавшее выражение вместо обратной ссылки? Чем он отличается от замещения?   -  person pogo    schedule 16.10.2012
comment
@newfurniturey да, возможно, количество повторений произвольно в момент определения шаблона, подобного \da{\1}, но шаблон в (.+) \1 тоже. Так как же это влияет на реализацию алгоритма? Я думаю, что \da{\1} точно такой же, как (.+) \1 с точки зрения реализации.   -  person crsxl    schedule 16.10.2012
comment
Кроме того, попробуйте re.compile('\da{\1}', re.DEBUG) и посмотрите, что получится. Он интерпретирует { и } как литералы (как если бы перед ними стояла обратная косая черта), а не как специальные. Сравните с re.compile('\da{1}', re.DEBUG).   -  person    schedule 16.10.2012
comment
@Evert Спасибо за напоминание, это подтверждено. Таким образом, этот вид обратной ссылки не поддерживается самим языком, поскольку он понимается компилятором как другой литерал.   -  person crsxl    schedule 17.10.2012


Ответы (1)


Интересная идея, но я думаю, что "{n}" обрабатывается при компиляции регулярного выражения.

Вы можете сделать что-то вроде этого:

>>> import re
>>> text = '3aaa'
>>> m = re.search('(\d+)a', text)
>>> pat = '\d+a{%s}' % m.group(1)
>>> n = re.search(pat, text)
>>> n.group(0)
'3aaa'

Если вы хотите исключить такие шаблоны, как «3aaaaa», вам понадобится «\ b» в конце шаблона (который Python заставляет вас вводить как «\ b»):

pat = '\d+a{%s}\\b' % m.group(1)
person cheapwax    schedule 21.11.2012