1

I am looping through an array of objects and mapping them to my own custom objects. I am extracting data via regular expressions. My first run through the loop works fine, but in subsequent iterations, although they match, the match variables do not get set.

Here is one of the regex's:

var gameRegex   = /(\^?)([A-z]+)\s?(\d+)?\s+(at\s)?(\^?)([A-z]+)\s?(\d+)?\s\((.*)\)/g;

Here is the initial part of my loop:

for(var i = 1; i <= data.count; i++) {
    var gameMatch = gameRegex.exec(data["left" + i]);
    var idMatch = idRegex.exec(data["url" + i]);

First time through, gameMatch and idMatch have values. The following iterations do not work even though I have tested that they do work.

Is there something about regular expressions, maybe especially in Node.js, that I need to do if I use them more than once?

Benny
  • 3,899
  • 8
  • 46
  • 81

1 Answers1

2

When you have a regular expression with a global flag /.../g and use exec() with it, JavaScript sets a property named lastIndex on that regex.

s = "abab";
r = /a/g;
r.exec(s);    // ["a"]
r.lastIndex   // 1
r.exec(s);    // ["a"]
r.lastIndex   // 3
r.exec(s);    // null
r.lastIndex   // 0

This is meant to be used for multiple matches in the same string. You could call exec() again and again and with every call lastIndex is increased - defining automagically where the next execution will start:

while (match = r.exec(s)) {
  console.log(match);
}

Now lastIndex will be off after the first invocation of exec(). But since you pass in a different string every time, the expression will not match anymore.

There are two ways to solve this:

  • manually set the r.lastIndex = 0 every time or
  • remove the g global flag

In your case the latter option would be the right one.


Further reading:

Tomalak
  • 332,285
  • 67
  • 532
  • 628