Если вы хотите убедиться, что есть заглавные и строчные буквы, вы можете использовать положительный прогноз 2 раза.
Если вы разрешите двойное повторение, но не 3 раза, вы можетеиспользуйте отрицательный взгляд, чтобы утверждать, что то, что справа, - это не то, что вы записали в классе charcter, а затем 2 раза обратная ссылка на то, что было захвачено:
^(?=.{8,20}$)(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?!.*([\w\d*?!:;])\1\1)[\w\d*?!:;]+$
В Java:
final String PASSWORD_PATTERN = "^(?=.{8,20}$)(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?!.*([\\w\\d*?!:;])\\1\\1)[\\w\\d*?!:;]+$";
Пояснение
^
Начало строки (?=.{8,20}$)
Утверждение цифры (?=.*[A-Z])
Утверждение заглавной буквы (?=.*[a-z])
Утверждение строчной буквы (?=.*[0-9])
Утверждение цифры (?!.*([\w\d*?!:;])\1\1)
Утверждение не повторяется 3 раза [\w\d*?!:;]+
Соответствует чемууказывается в классе символов 1+ раз $
Подтвердить конец строки
Regex demo
Обратите внимание, что если выиспользуйте (?=[^0-9]*[0-9])
класс отрицательных символов также будет соответствовать символам новой строки.