0

I have this simple regex that is supposed to match any numbers and '+' signs

/^[\d\+]+$/g

What it does is this:

1  => true
11 => false
11+11 => true
1+1 => false

It's driving me nuts!

(I'm using JavaScript, if it matters)

user3195878
  • 145
  • 6
  • What are you trying to? What do you want to match and what do you not want to match? – putvande Feb 01 '14 at 13:43
  • 1
    @bnjmn: But there is a `+` after the character class. This regex *should* match - there must be some other problem. – Tim Pietzcker Feb 01 '14 at 13:43
  • 1
    That regex returns `true` when `test`ing it against all of those test cases that you provided... what browser are you running this on? – tckmn Feb 01 '14 at 13:43
  • @user3195878 It seems to work for us. Could you provide a [JSFiddle](http://jsfiddle.net) demonstrating the problem? – tckmn Feb 01 '14 at 13:46
  • @DoorknobofSnow thanks for correcting me, I'll eagerly wait and see :) If he wants just numbers (digit sequences) and *INFIX* plus signs, wouldn't this work (correct me if I'm wrong, again): `/^\d*[\+\d*]*$/g`? – pid Feb 01 '14 at 13:51
  • @pid No... well, yes technically that would work just as well, but it will also match `+`, `123***`, `++274*+*+`, and an empty string. – tckmn Feb 01 '14 at 14:04
  • I feel like an idiot, you're totally right! `\d` already is a character, class as you've already said before. Thanks for pointing that out! – pid Feb 01 '14 at 14:10

1 Answers1

4

Some assumptions I did when reproducing your error:

  1. You're using the test()-method of the RegExp-prototype, not the match()-method of the String-prototype.
  2. Your pattern is stored in a variable and you reuse it over multiple calls to the test()-method.

At a first glance, the result is somewhat unexpected, but I'll try to explain what is happening.

Your RegExp has the global-Flag set to true. This causes subsequent calls to the test()-method to advance past previous matches, as stated here. This essentially means that after your first regular expression is evaluated and a match was found, the index of this match is stored into the RegExp-object and the next match will start at that very index, omitting some characters at the beginning. For a deeper explanation, I'd recommend reading this thread.

This is not really what you want, right? My quick recommendation would be to simply remove the global-flag, as you don't really need it from my point of view. If you want to ensure that your regular expression is only matching full strings rather than substrings, use the ^and $ metacharacters (as you already did).


EDIT:

If you really need the global-flag though, try to use the match()-method of the String-prototype, as it does not advance past previous matches. Instead it uses the advancing feature and captures all matches, resetting the index afterwards.

var pattern = /^[\d\+]+$/g;
"1".match(pattern); // => true
"11+11".match(pattern); // => true
"1+1abc".match(pattern); // => false
Community
  • 1
  • 1
Conrad
  • 581
  • 4
  • 9
  • 1
    You had it right the first time; it makes no sense to use the `g` flag with a regex that's anchored at one or both ends. – Alan Moore Feb 01 '14 at 14:34
  • Yeah, that was the gotcha. For convenience's sake I put all my test values in an array and looped over it. The g flag was indeed the cuplrit. Thanks! – user3195878 Feb 01 '14 at 14:45