As far as my limited skills can determine, you have basically two options:
- Make your regex include all possible 3-out-of-4 permutations and separate them with "or" using |
- Split your matches out into separate regexes, and count how many of them match.
Neither is particularly brief, but I think the latter is more concise and readable.
Here's my example of that solution:
if (3 <= scalar grep { $str =~ /$_/ } ( # Match at least 3 of:
qr/^.*(?=.{10,})(?=.*\d).*$/,
qr/^.*(?=.{10,})(?=.*[a-z]).*$/,
qr/^.*(?=.{10,})(?=.*[A-Z]).*$/,
qr/^.*(?=.{10,})(?=.*[@#$%^&+=]).*$/
)
) {
# Do something.
}