7

The problem is next. I created an input field which has validation and this is valid data:

  1. 1-12, 14, 16, 22, 25-35, 41, 49, 55-90
  2. 1230-1992, 2001-2099, 9931
  3. 1-2
  4. 13
  5. 1,3,4,5,6,10
  6. all

Basically, any combination of those numbers (ranges, comma-separated ranges, comma-separated number, spaces after commas, no spaces after commas, word: 'all')

My RegEx: /^(([0-9]{0,4},?\s{0,})+([0-9]{1,4}-[0-9]{1,4}){0,},?\s{0,})+$|^(all)$|^([0-9]{1,4}-[0-9]{1,4}){0,},?\s{0,}$/

It works almost fine, there is only 1 major problem.

When I start typing, and after some comma-separated numbers I add something that is not valid, like characters: 'abc' - and at this moment my browser tab stucks.

Try this as an input: 1-12, 14, 16, 19, 20-29, was

Fiddle to test: http://jsfiddle.net/c9ahfhqy/

Is there any suggestions on how the proper RegEx should look like?

Code:

    $("input[type='text']").blur(function() { //when you lose focus on input
      doneTyping();
    });

    function doneTyping() {
      if(!$('#inputToCheck').val().match(/^(([0-9]{0,4},?\s{0,})+([0-9]{1,4}\-[0-9]{1,4}){0,},?\s{0,})+$|^(all)$|^([0-9]{1,4}\-[0-9]{1,4}){0,},?\s{0,}$/)) {
        console.log("Not Valid");
      } else {
        console.log("Valid");
      }
    }

Really appreciate help.

admix
  • 1,752
  • 3
  • 22
  • 27
  • 2
    **It's not the regex**, it's the code that's using the regex, probably an infinite loop or something similar, but you didn't post any code, so we can't help you, instead we're going to close the question. – adeneo Aug 21 '14 at 18:26
  • `$("input[type='text'])` -- looks like you missed a quote. – amphetamachine Aug 21 '14 at 18:36
  • Thanks for noticing. Added quote to the question. Unfortunately it is not a problem. :( – admix Aug 21 '14 at 18:38
  • Fiddle to demonstrate the problem: http://jsfiddle.net/r5t13784/1 – apsillers Aug 21 '14 at 18:41
  • Oops. Changed that. A little bit in a hurry... sorry for typos. – admix Aug 21 '14 at 18:41
  • @apsillers your fiddle reproduces my bug... I typed: **1-12, 14, 16, 19, 20-29, was** It stucks right after that. – admix Aug 21 '14 at 18:43
  • Given the syntax errors being pointed out, it seems that this isn't an exact representation of your actual code. Is that correct? – cookie monster Aug 21 '14 at 18:43
  • @admix I misunderstood your error test case. With that input, yes, I see it. – apsillers Aug 21 '14 at 18:44
  • @cookiemonster Whether or not it's really the OP's actual code, my fiddle demonstrates the OP's issue as described using the OP's code as presented in the question. (I previous thought it didn't, but I didn't understand the error case.) – apsillers Aug 21 '14 at 18:46
  • 1
    Oh, I think you have a recursive loop inside a recursive loop (or something like that), making for a lot of work for the regex. There's an article somewhere around the web that explains this. I'll see if I can find it. – cookie monster Aug 21 '14 at 18:47
  • @cookiemonster thank you. Is there maybe more efficient solution for regex to match that case? – admix Aug 21 '14 at 18:49
  • 1
    @adeneo Turns out it actually is the regex; the problem can be simply reproduced by `/^(([0-9]{0,4},?\s{0,})+([0-9]{1,4}-[0-9]{1,4}){0,},?\s{0,})+$|^(all)$|^([0-9]{1,4}-[0-9]{1,4}){0,},?\s{0,}$/.exec("1-12, 14, 16, 19, 20-29, was")` – apsillers Aug 21 '14 at 18:49
  • @derp: Yep, just found that article too. Thanks for posting it. – cookie monster Aug 21 '14 at 18:51
  • @apsillers - well, there you go, I don't think I've ever seen catastrophic backtracking in javascript, I can only vaguely remember reading about it years ago, so it's not a very common issue, and adding context to the question sure does help anyway. – adeneo Aug 21 '14 at 19:23

1 Answers1

5

As @derp said, your regex has a problem of Catastrophic Backtracking.

The following one seems to work like you want, and doesn't freeze the browser:

/^(?:all|\d{1,4}(?:-\d{1,4})?(?:,\s*\d{1,4}(?:-\d{1,4})?)*)$/

Demo

Using RegexBuddy's debugger to test 1-12, 14, 16, 19, 20-29, was,

  • You regex fails after attempting 1000000 steps, with this error:

    Your regular expression is too complex to continue debugging.
    The regex engine you plan to use it with may not be able to handle it at all and crash.
    Look up "catastrophic backtracking" in the help file to learn how to avoid this situation.

  • The regex above fails after 96 steps, with no error.

Community
  • 1
  • 1
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • @admix Not at all :) Thanks to you too, previously I didn't know about catastrophic backtracking, nor RegexBuddy's debugger. – Oriol Aug 21 '14 at 19:21