First, let's shorten the pattern as it contains two next-to identical alternatives, one matching SSN with hyphens, and the other matching the SSN numbers without hyphens. Instead of ^(x-y-z$|xyz$)
pattern, you can use a ^x(-?)y\1z$
pattern, so your regex can get reduced to ^(?!000|666)[0-8][0-9]{2}(-?)(?!00)[0-9]{2}\1(?!0000)[0-9]{4}$
, see this regex demo here.
To make a pattern never match a string that contains only identical digits, you may add the following negative lookahead right after ^
:
(?!\D*(\d)(?:\D*\1)*\D*$)
It fails the match if there are
\D*
- zero or more non-digits
(\d)
- a digit (captured in Group 1)
(?:\D*\1)*
- zero or more occurrences of any zero or more non-digits and then then same digit as in Group 1, and then
\D*$
- zero or more non-digits till the end of string.
Now, since I suggested shortening the regex to the pattern with backreference(s), you will have to adjust the backreferences after adding this lookahead.
So, your solution looks like
^(?!\D*(\d)(?:\D*\1)*\D*$)(?!000|666)[0-8]\d{2}(-?)(?!00)\d{2}\2(?!0000)\d{4}$
^(?![^0-9]*([0-9])(?:[^0-9]*\1)*[^0-9]*$)(?!000|666)[0-8][0-9]{2}(-?)(?!00)[0-9]{2}\2(?!0000)[0-9]{4}$
Note the \1
in the pattern without the lookahead turned into \2
as (-?)
became Group 2.
See the regex demo.
Note also that in some regex flavors \d
is not equal to [0-9]
.