tags:

views:

38

answers:

2

I am using the following Javascript to read strings out of a text file and process them with a regular expression

while (!textFile.AtEndOfStream)
{
    currLine = textFile.ReadLine();
    match = re.exec(currLine);
    do stuff with match
}

The problem I have is that every other time re.exec is called it fails and returns null; so the first row is processed correctly, but the second row results in null, then the third row works, and the fourth row results in null.

I can use the following code to get the result I want

while (!textFile.AtEndOfStream)
{
    currLine = textFile.ReadLine();
    match = re.exec(currLine);
    if (match == null) match = re.exec(currLine);
}

but that seems a bit of a nasty kludge. Can anyone tell my why this happens and what I can do to fix it properly?

+2  A: 

Javascript regular expressions keep some state between executions and you are probably falling in to that trap.

I always use the String.match function and have never been bitten :

while (!textFile.AtEndOfStream)
{
    match = textFile.ReadLine ().match (re);
    do stuff with match
}
Hans B PUFAL
+4  A: 

Your re is defined with the ‘global’ modifier, eg. something like /foo/g.

When a RegExp is global, it retains hidden state in the RegExp instance itself to remember the last place it matched. The next time you search, it'll search forward from the index of the end of the last match, and find the next match from there. If you're passing a different string to the one you passed last time, this will give highly unpredictable results!

When you use global regexps, you should exhaust them by calling them repeatedly until you get null. Then the next time you use it you'll be matching from the start of the string again. Alternatively you can explicitly set re.lastIndex to 0 before using one. If you only want to test for the existence of one match, as in this example, simplest is just not to use g.

The JS RegExp interfaces is one of the most confusing, poorly-designed parts of the language. (And this is JavaScript, so that's saying a lot.)

bobince
+1, deleted mine in favour of this. I wanted to expand on mine but I got sidetracked :-)
Andy E
Thanks for the excellent answer bobince. I've removed the g and it works perfectly now.
Pandelon