-2

I'm trying to verify card numbers using REGEX. All characters must be digits (0-9), if the first digit is 3 the number can either be 15 or 16 characters long, if the number doesn't start with 3, it must be 16 characters long.

Is there a way to use conditional statements in pure regex, not using an external library?

Josh Smith
  • 339
  • 4
  • 7
  • How about _first_ checking what the first digit is, using the dirt simple `yourString.charAt(0)`, and using that result to determine which method to call to ensure appropriate format validation? – Mike 'Pomax' Kamermans Oct 03 '20 at 22:12

3 Answers3

0

Yes, you can make regex conditional using operator | (OR)

/(^3\d{14,15}$)|(^[^3]\d{16}$)/
Ihor Yanovchyk
  • 600
  • 5
  • 12
  • This regex matches a string starting with 3 plus 16 digits - 17 chars total – Alex Rudenko Oct 03 '20 at 22:24
  • @AlexRudenko, yes you are right! – Ihor Yanovchyk Oct 03 '20 at 22:25
  • There's worse bug with the number not starting with 3 - it _must have_ 17 chars :) – Alex Rudenko Oct 03 '20 at 22:40
  • This solved my issue, thanks @AlexRudenko, changed the non-3 condition to 15 and it worked perfectly. Only other issue is that strings that don't start with 3 also don't require a digit input for the first character, any thoughts on that? – Josh Smith Oct 03 '20 at 22:42
  • @JoshSmith what is allowed then as the first character? I doubt that _any_ character (including whitespace, punctuation, etc.) may be used in the card numbers. – Alex Rudenko Oct 03 '20 at 22:46
  • @AlexRudenko Only digits should be allowed. Right now, the second condition allows any character that isn't a 3, it should still only allow digits as the first character. (e.g. 'a111111111111111' passes the 2nd condition even though it should only accept '1111111111111111' or any other combination of digits). – Josh Smith Oct 03 '20 at 22:53
  • @JoshSmith You may check [my answer](https://stackoverflow.com/a/64189532/13279831) – Alex Rudenko Oct 03 '20 at 22:55
0

Yes, it is possible with a regexp like this where | is used as a logical OR, and intial conditions may be simplified:

String regex = "^(3\\d{14}|\\d{16})$";

where: 3\\d{14} - check the first condition - start with 3, could be 15 chars long (including leading 3)

OR

\\d{16} - any digits, strictly 16 chars long

online demo

Alex Rudenko
  • 15,656
  • 9
  • 13
  • 33
  • This was almost what I needed: final string was "(^3\d{14,15}$)|(^\d{16}$)" needed to add the beginning of string character at the beginning of 2nd test condition. – Josh Smith Oct 03 '20 at 23:06
  • `(^3\d{14,15}$)|(^\d{16}$)` - here validation of start/end is duplicated and may be moved outside groups; `3\d{15}` is consumed by `\d{16}` but if you like it better that's ok – Alex Rudenko Oct 03 '20 at 23:11
  • That's a good point. Removed the duplicate, thanks. – Josh Smith Oct 03 '20 at 23:44
0

Similar to @withrp answer but with lookaheads

^(?=[3])([0-9]{15,16})|(?=[0-24-9])([0-9]{16})$
JBone
  • 1,176
  • 2
  • 13
  • 25