Почему первое чередование не совпадает?
У меня есть следующее регулярное выражение (Python), которое я не понимаю в следующем пункте. Почему оно не соответствует первому чередованию?
Regex (для лучшего понимания):
(?:
\$\{
(?P<braced>
[_a-zA-Z][a-zA-Z0-9]*(?::[_a-zA-Z][_a-zA-Z0-9]*)+
)
\}
)
| ### SECOND ALTERNATION ###
(?:
\$
(?P<named>
[_a-zA-Z][a-zA-Z0-9]*(?::[_a-zA-Z][_a-zA-Z0-9]*)+
)
)
Тестовая строка:
asdasd $ asd: sd + $ {asd123: asd} $ HOME $$ asd
Подходящие вещи:
asdasd $ asd: sd + $ {asd123: asd} $ HOME $$ asd
Согласно приведенному выше шаблону регулярных выражений также должно появиться первое чередование, а именно:
${asd123:asd}
Кажется, я не совсем понимаю шаблон чередования?
3 ответа
Для того, чтобы захватить ${...}
нужно удалить ?:
превратить не захватывающие группы в захватывающие. Вы также можете сделать их именными. Также [_a-zA-Z0-9] равно \ w, поэтому мы можем немного сократить ваше регулярное выражение:
(?P<Alternation1>
\$\{(?P<braced>[_a-zA-Z][a-zA-Z0-9]*(?::[_a-zA-Z]\w*)+)
\}
)
|
(?P<Alternation2>
\$(?P<named>[_a-zA-Z][a-zA-Z0-9]*(?::[_a-zA-Z]\w*)+
)
)
Посмотрите на демо. Это регулярное выражение требует использования x
вариант (и g
опции на regex101.com, чтобы показать все совпадения, в Python вы бы использовали findall
или же finditer
).
Дополнительную информацию о группах без захвата можно получить на SO и по адресу регулярно-expressions.info.
Чтобы просто получить все совпадения в Python, вы можете использовать finditer
как это:
import re
p = re.compile(ur'''(?P<Alternation1>
\$\{(?P<braced>[_a-zA-Z][a-zA-Z0-9]*(?::[_a-zA-Z]\w*)+)
\}
)
|
(?P<Alternation2>
\$(?P<named>[_a-zA-Z][a-zA-Z0-9]*(?::[_a-zA-Z]\w*)+
)
)
''', re.VERBOSE)
test_str = u"asdasd $asd:sd + ${asd123:asd} $HOME $$asd"
print [x for x in re.findall(p, test_str)]
Посмотреть демо IDEONE
Вам нужно добавить g
модификатор, чтобы получить все совпадения на regex101.com
Ваш шаблон работает хорошо, все, что вам нужно, это использовать его с finditer
провести глобальное исследование и получить полное совпадение:
>>> for m in re.finditer(pattern, text):
... print 'whole match: %s' (m.group(0))
... print 'group "braced": %s' % (m.group('braced'))
... print 'group "named": %s\n' % (m.group('named'))
(Проблема с findall
(который также выполняет глобальное исследование) в том, что когда в шаблоне есть группы захвата, результат содержит только список содержимого групп захвата, а не весь результат сопоставления. Так что объединение всех в группу захвата, как предложил Стрибижев, может быть способом findall
).