ray
ray

Reputation: 8699

No repeating sequence in SSN (e.g. 123-12-3123)

How would you rule out a repeating sequence for SSN via regex?

For instance, the following values would be disallowed:

    123-12-3123
    456-45-6456
    789-78-9789

UPDATE

What constitutes repeating? *Does* 121-233-4444 count?

Good question, but no; at least not yet. I'm the code-monkey filling in a request from A&D who, in turn, is fulfilling a request from the client.

They are specifically asking for a fix to prevent users from entering a sequence of 3 numbers repeating 3 times. The most common would be the ones listed above.

What language are you using?

javascript

Also, I'm appending this regex on an existing REGEX that's buried deep in an enterprise level application with thousands of users. Adding code is possible, but not at all desirable.

Upvotes: 2

Views: 601

Answers (2)

Sam Choukri
Sam Choukri

Reputation: 1904

First remove non-digits:

$ssn =~ s/\D+//g;

Then check for repeating groups of three digits:

if ($ssn =~ /(\d{3})\1\1/) {
  print "ssn has repeating digits: $1\n";
}

Upvotes: 0

ikegami
ikegami

Reputation: 386386

Your question isn't clear. I'm assuming you want xyz-xy-zxyz where x+1 = y and y+1 = z.

There's no good answer.

Brute force:

/
   ^
   (?: 012-01-2012
   |   123-12-3123
   |   234-23-4234
   |   345-34-5345
   |   456-45-6456
   |   567-56-7567
   |   678-67-8678
   |   789-78-9789
   )
   \z
/x

The above can be built dynamically:

my @alts;
for (0..7) {
   my ($x, $y, $z) = ($_+0, $_+1, $_+2);
   push @alts, "$x$y$z-$x$y-$z$x$y$z";
}

my $alt = join('|', @alts);

/^(?:$alt)\z/

There's no need to validate, so one could use:

/
   ^
   (?: 01-?2-? | 12-?3-? | 23-?4-? | 34-?5-?
   |   45-?6-? | 56-?7-? | 67-?8-? | 78-?9-?
   ){3}
   \z
/x

If your programming language has the option of embedding code:

/
   ^
   ( [0-7] )
   ( (??{ $1+1 }) )
   ( (??{ $1+2 }) )
   -
   \1 \2
   -
   \3 \1 \2 \3
   \z
/x

You could widen your net:

/
   ^
   ( [0-9] )( [0-9] )( [0-9] )
   -
   \1 \2
   -
   \3 \1 \2 \3
   \z
/x

If you don't want to widen your net, you could also use code outside of the regex:

/
   ^
   ( [0-7] )
   ( [1-8] )
   ( [1-9] )
   -
   \1 \2
   -
   \3 \1 \2 \3
   \z
/x && $2 == $1+1 && $3 == $2+1

And then there's this:

s/-//g;
/
   ^
   (?: 012 | 123 | 234 | 345
   |   456 | 567 | 678 | 789
   ){3}
   \z
/x

For simplicity's sake, I strongly recommend you remove non-digits before doing the check.

/^[0-9]{3}-[0-9]{2}-[0-9]{4}\z/
   or die;

s/-//g;

... check here...

Upvotes: 3

Related Questions