Вы получаете дополнительный результат, потому что (1) вы используете findall()
вместо search()
и (2) вы используете группы захвата вместо незахвата
>>> import re
>>> re.search(r'^(?:(?:(?!exclude).)*(?=test)*)$', "/this/test").group(0)
'/this/test'
Это будет работать и с findall()
, но это не имеет смысла, когда вы сопоставляете всю строку. Что еще более важно, часть include вашего регулярного выражения не работает. Проверь это:
>>> re.search(r'^(?:(?:(?!exclude).)*(?=test)*)$', "/this/foo").group(0)
'/this/foo'
Это потому, что *
в (?=test)*
делает просмотр вперед необязательным, что делает его бессмысленным. Но избавление от *
на самом деле не является решением, потому что exclude
и test
могут быть частью более длинных слов, таких как excludexx
или yyytest
. Вот лучшее регулярное выражение:
r'^(?=.*/test\b)(?!.*/exclude\b)(?:/\w+)+$'
проверено:
>>> re.search(r'^(?=.*/test\b)(?!.*/exclude\b)(?:/\w+)+$', '/this/test').group()
'/this/test'
>>> re.search(r'^(?=.*/test\b)(?!.*/exclude\b)(?:/\w+)+$', '/this/foo').group()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
РЕДАКТИРОВАТЬ: я вижу, вы исправили проблему "необязательный просмотр вперед", но теперь все регулярное выражение является необязательным!
EDIT: Если вы хотите, чтобы совпадения прекратились после /test
, попробуйте следующее:
r'^(?:/(?!test\b|exclude\b)\w+)*/test\b'
(?:/(?!test\b|exclude\b)\w+)*
соответствует нулю или более компонентам пути, если они не равны /test
или /exclude
.
person
Alan Moore
schedule
18.10.2012