Использование негативного взгляда или взгляд назад решит вашу проблему. Есть 2 варианта, не ясных из вопроса:
?uid=100
не допускается после начальной части /bar/baz
, поэтому www.mysite.com/test/bar/baz?uid=100
должно быть действительным. ?uid=100
не допускается в любом месте в строке, следующей за /bar/baz
, что означает, что www.mysite.com/test/bar/baz/?uid=100
также недопустимо.
Опция 1
Вкратце:
\/(test|foo|bar\/baz(?!\/?\?)|en|ppp)(\/[-\w?=]+)*\/?
Объяснение важных частей:
| # OR
bar # 'bar' followed by
\/ # '/' followed by
baz # 'baz'
(?! # (negative lookahead) so, **not** followed by
\/? # 0 or 1 times '/'
\? # '?'
) # END negative lookahead
и
( # START group
\/ # '/'
[-\w?=]+ # any word char, or '-','?','='
)* # END group, occurrence 0 or more times
\/? # optional '/'
Примеры Вариант 1
Вы можете сделать предпросмотр еще более точным, указав c, например, (?!\/?\?\w+=\w+)
, чтобы явно указать, что ?a=b
недопустимо, но это зависит от вас.
Опция 2
Чтобы сделать явным то, что ?a=b
недопустимо в любом месте мы можем использовать отрицательный взгляд позади . Давайте сначала найдем решение для , а не , позволяющее * bar/baz
предшествовать ?a=b
.
Сокращение:
(?<!bar\/baz\/?)\?\w+=\w+
Объяснение:
(?<! # Negative lookbehind: do **not** match preceding
bar\/baz # 'bar/baz'
\/? # optional '/'
)
\? # match '?'
\w+=\w+ # match e.g. 'a=b'
Давайте сделаем эту часть полного регулярного выражения:
\/(test|foo|en|ppp|bar\/baz)(\/?((?<!bar\/baz\/?)\?\w+=\w+|[-\w]+))*\/?$
Объяснение:
\/ # match '/'
(test|foo|en|ppp|bar\/baz) # start with 'test', 'foo', 'en', 'ppp', 'bar/baz'
(\/? # optional '/'
((?<!bar\/baz\/?)\?\w+=\w+ # match 'a=b', with negative lookbehind (see above)
| # OR
[-\w]+) # 1 or more word chars or '-'
)* # repeat 0 or more times
\/? # optional match for closing '/'
$ # end anchor
Примеры Вариант 2