15

Javascript Regular Expression is working fine first time but not second time, working again for 3rd time and not for 4th and so on :(

Script :

<script language="javascript" type="text/javascript">
    var reg = /[^\w]/gi;
    function checkNonWordChars() {
        var str = $("#TestTextbox").val();
        if (reg.test(str)) {
            alert('!!! Non-Word Char Exists !!!');
        }
        else {
            alert('input accepted');
        }
    }    
</script>

HTML :

<input type="text" id="TestTextbox"  />
<input type="button" value="Test" onclick="checkNonWordChars();" />

If I click on button once, it will fire an alert saying that “!!! Non-Word Char Exists !!!” but if I click it again, it will fire an alert saying “input accepted” :(

durron597
  • 31,968
  • 17
  • 99
  • 158
Nilesh Thakkar
  • 1,442
  • 4
  • 25
  • 36

4 Answers4

19

I suspect it has something to do with the fact that using the g modifier makes the engine remember its state.

Try removing the g modifier, you do not need it anyway. The engine will always try to find a match in the whole string. Hence, the g modifier does not really do anything in combination with the test function, but is rather used for match. You also don't need the i modifier by the way, since \w includes both lower-case and upper-case letters.

And one last thing. Regular expressions provide the convenient \W which is the opposite \w and thus equivalent to [^\w].

Community
  • 1
  • 1
Martin Ender
  • 43,427
  • 11
  • 90
  • 130
8

OPTION 1

Use the constructor rather than the literal notation:

var reg = new RegExp('[^\w]','gi');

More about differences between the two here: https://developer.mozilla.org/en-US/docs/Core_JavaScript_1.5_Guide/Regular_Expressions?redirect=no

OPTION 2

Mark the end of the string with a $ sign:

var reg = /[^\w$]/gi;

OPTION 3

If your regular expression uses the "g" flag, you can use the exec method multiple times to find successive matches in the same string. When you do so, the search starts at the substring of str specified by the regular expression's lastIndex property (test will also advance the lastIndex property).

Source: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/RegExp/exec

Therefore, in your case the test will work only 1st, 3rd, 5th, ... time.

Only in Firefox 3 there is a flag y , when specified exec always starts from 0 not lastIndex but this is probably not useful in your case.

You can remove the g flag.

sainiuc
  • 1,697
  • 11
  • 13
  • 1
    OPTION 1 works fine, not OPTION 2, Anyways thank you for your post – Nilesh Thakkar Nov 05 '12 at 15:06
  • Your regex in option 2 is wrong. You are just adding the "$" character to the character class, you wanted `var reg = /[^\w]$/gi;`. But anyway, I think this would not be what the OP wanted, that would only check if the last character in the string is a non-word character. – stema Nov 06 '12 at 08:49
1

It seems that the RegExp object is not as stateless as we think. A quick fix is to move var reg = /[^\w]/gi; inside the checkNonWordChars() method

Best Regards,

Nilesh Thakkar
  • 1,442
  • 4
  • 25
  • 36
Esteban Aliverti
  • 6,259
  • 2
  • 19
  • 31
  • 1
    Yes, its a quick fix but a bad idea when i am using the same expression multiple times – Nilesh Thakkar Nov 05 '12 at 14:25
  • Alternatively, if the expression is used in various places in the script, and you don't want to create 1001 RegExp instances, `reg.compile(reg)` might work, though `compile` is considered deprecated – Elias Van Ootegem Nov 05 '12 at 14:28
0

If you need to have that regex global, then change it to:

var reg = /[^\w]/

It will work just as well, but not be buggy! It will be faster too, because it only needs to check for one instance of a naughty character, and you don't care about character case with non-word characters.

Ethan B. Martin
  • 174
  • 1
  • 3