I think this will be more compact than listing each possible combination of 3 out of 4. It uses a negative scan to make sure that the entire string does not consist of just one or two of the character classes you listed:
(?!([a-zA-Z]*|[az\d]*|[^AZ\d]*|[AZ\d]*|[^az\d]*|[^a-zA-Z]*)$).*
In order, the following groups are here:
- lower and / or upper
- below and / or numbers
- lower and / or special
- upper and / or numbers
- top and / or special
- numbers and / or special
This regular expression will fail if the entire string (due to $ in a negative image) contains only characters from any of the above groups.
source share