Наилучшим механизмом объединения нескольких тестов в одном регулярном выражении является lookahead .Обычное регулярное выражение перемещается по строке в поисках совпадения, что означает, что когда оно находит совпадение, оно больше не находится в начале строки.Lookahead ищет совпадение , фактически не перемещаясь (отсюда и название "lookahead").Базовый формат - (?=<regex>)
, и вы можете объединить столько, сколько хотите, в один шаблон.
В этом случае у вас есть два условия, поэтому вы захотите объединить два заглядывания.Мы уже видели первый - .{8,}
- но в перспективе вам нужно немного больше: вам нужно убедиться, что регулярное выражение соответствует всей строке.Так что начните свой паттерн с \A
, якорь соответствует началу строки, и завершите просмотр с \z
, якорь соответствует концу строки.Положите его вместе, и первая часть вашего шаблона будет \A(?=.{8,}\z)
.(Эта мера предосторожности не требуется в вашем конкретном случае, потому что вы будете принимать пароли длиной более восьми символов, но это все же хорошая практика.)
Второе условие, соответствующее любому из восьми конкретных символов, начинается с класса[!@#$%^&*]
.Но в заглядывании, которое начинается в начале строки и никогда не движется, этот класс будет соответствовать только первому символу.Вам нужно регулярное выражение, которое соответствует в любом месте строки.Простой способ сделать это - .*[!@#$%^&*]
, который соответствует нулю или более символов, за которыми следует один из ваших специальных символов.В перспективе это будет (?=.*[!@#$%^&*])
.«Легкий» не всегда лучший, однако: конструкция .*
сравнительно неэффективна, поскольку она всегда проверяет всю строку и затем должна вернуться к началу, прежде чем продолжить, что может быть вычислительно дорогостоящим.
Aгораздо более эффективный способ сделать что-то вроде этого - [^!@#$%^&*]*[!@#$%^&*]
.Это соответствует нулю или более символов, которые не в вашем специальном наборе, за которыми следует ровно один символ, который есть(Знак вставки (^
) в качестве первого символа в классе в скобках означает отрицание класса; знак вставки в любом другом месте класса является просто буквальным символом в качестве члена класса.) Он более эффективен, поскольку проверяет толькосимволы перед его позицией в строке, и могут сразу же остановиться, как только найдет совпадение.Помещение этого в заголовок дает нам (?=[^!@#$%^&*]*[!@#$%^&*])
.
Теперь вы можете просто объединить два заголовка в свой «шаблон», например, так:
pattern='\A(?=.{8,}\z)(?=[^!@#$%^&*]*[!@#$%^&*])'
Это должно соответствовать любому паролю с восемьюили более символов, по крайней мере один из которых является одним из восьми специальных символов:!@ # $% ^ & *