It's not that hard:
( # Start of group
(?=.*\d) # must contain at least one digit
(?=.*[A-Z]) # must contain at least one uppercase character
(?=.*[a-z]) # must contain at least one lowercase character
(?=.*\W) # must contain at least one special symbol
\w
. # match anything with previous condition checking
{6,18} # length is characters
\w
) # End of group
In one line:
((?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*\W)\w.{6,18}\w)
If you do not like \w
which is equal to [a-zA-Z0-9_]
replace it with that group and remove the underscore.
However, I fully support ctwheels' argument.
[a-z]
to ensure lowercase letters (same goes for uppercase letters, numbers and special characters. Adding the logic that doesn't allow a password to begin and end with a special character also reduces the number of potential passwords, thus making your systems less secure. Your team should definitely re-evaluate password policies. – ctwheels