13

I'm trying to limit the entries to a specific format.

If the entry has 5500 or 5100 such as 01\01-5500-000-00 then I want to have this:

^[0-9]{2,}\\[0-9]{2}\-[0-9]{4}\-[0-9]{3}\-$

But if the entry has anything other than 5500 or 5100 I want to have this:

^[0-9]{2,}\\[0-9]{2}\-[0-9]{4}\-[0-9]{3}\-[0-9]{2}$

How can this be accomplished with the if then else idea?

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
user974061
  • 343
  • 1
  • 5
  • 17
  • 4
    What language are you using? What have you tried? – Sam Sep 29 '15 at 20:09
  • `^[0-9]{2,}\\[0-9]{2}-5[15]00-[0-9]{3}-$|^[0-9]{2,}\\[0-9]{2}-(?!5[15]00)[0-9]{4}-[0-9]{3}-[0-9]{2}$` – Ulugbek Umirov Sep 29 '15 at 20:13
  • I've used http://www.webtoolkitonline.com/regular-expression-tester.html to help me correctly create the expression. And I've tried using the pipe with 5500 in parenthesis like this: (?=.*5500)|^[0-9]{2,}\\[0-9]{2}\-[0-9]{4}\-[0-9]{3}\-[0-9]{2}$ - not correct – user974061 Sep 29 '15 at 20:15
  • That tool only supports JS as I can see. But it is still possible. – Wiktor Stribiżew Sep 29 '15 at 20:18
  • By the way, `01\01-5500-000-00` does not match your first pattern. is it supposed to fail? Also, is the trailing `"-"` in the first pattern intentional? – Mariano Sep 29 '15 at 20:43

3 Answers3

19

Conditional regex syntax is not supported by JavaScript regex engine, but it can be worked around with a non-capturing group containing 2 alternatives:

  1. One with the positive look-ahead and

  2. The second with the reversed, negative look-ahead.

This regex meets your criteria and is JavaScript compatible:

^(?:(?=.*\b5[15]00\b)[0-9]{2,}\\[0-9]{2}-[0-9]{4}-[0-9]{3}-|(?!.*\b5[15]00\b)[0-9]{2,}\\[0-9]{2}-[0-9]{4}-[0-9]{3}-[0-9]{2})$

See regex demo

Let me break it down:

  • ^ - Start of string
  • (?:
    • (?=.*\b5[15]00\b)[0-9]{2,}\\[0-9]{2}-[0-9]{4}-[0-9]{3}- - First alternative with the (?=.*\b5[15]00\b) look-ahead that requires a whole word 5500 or 5100 inside the string, and the first pattern you have
    • | - alternation operator
    • (?!.*\b5[15]00\b)[0-9]{2,}\\[0-9]{2}-[0-9]{4}-[0-9]{3}-[0-9]{2}) - Second alternative that is prepended with the (?!.*\b5[15]00\b) negative look-ahead that makes sure there is no 5100 or 5500 inside the string, and only then matches your second pattern.
  • $ - end of string.
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
3

Use conditionals, Eg:

(?(?=regex)then|else): [0-9]{2,}\\[0-9]{2}\-(?(?=5[15]00)[0-9]{4}\-[0-9]{3}\-|[0-9]{4}\-[0-9]{3}\-[0-9]{2})

Regex conditionals example: conditionals@regex101.com

In case that you're using a regex engine that is not PCRE based, you can be able to mimic the functionality by doing the following:

((?=positive-regex-statement)then|(?!negavite-regex-statement)then)

Eg.

^[0-9]{2,}\\[0-9]{2}\-((?=5[15]00)[0-9]{4}\-[0-9]{3}\-|[0-9]{4}\-|(?!5[15]00)[0-9]{4}\-[0-9]{3}\-[0-9]{2})$

Mimic regex conditionals example: mimic@regex101.com

revo
  • 47,783
  • 14
  • 74
  • 117
Eder
  • 1,874
  • 17
  • 34
  • 2
    @user974061: Could you please advise what is the programming language that you are using with this regular expressions? (The conditionals are supported only by PCRE like engines). – Eder Sep 29 '15 at 20:25
  • @Houseman: Did you actually read the whole post, or just down-voted for no reason? I provided an answer for non PCRE based engines (which also includes Javascript). – Eder Mar 04 '16 at 22:47
  • 2
    Thanks for fixing that, @Revo, I was a little confused. – alfadog67 Oct 08 '16 at 16:41
2

Replace this part of the pattern [0-9]{4} with the literal values for 5100/5500:

/^\d{2,}\\\d{2}-(?:5[15]00-\d{3}-|(?!5[15]00)\d{4}-\d{3}-\d{2})$/
  • [0-9] is the same thing as \d in JavaScript
  • For the else part, use the negative lookahead (?!5[15]00)\d{4} to guarantee it's not 5100/5500.
Mariano
  • 6,423
  • 4
  • 31
  • 47