Why does a RegExp with global flag give wrong results?

Viewed 56879

What is the problem with this regular expression when I use the global flag and the case insensitive flag? Query is a user generated input. The result should be [true, true].

var query = 'Foo B';
var re = new RegExp(query, 'gi');
var result = [];
result.push(re.test('Foo Bar'));
result.push(re.test('Foo Bar'));
// result will be [true, false]

var reg = /^a$/g;
for(i = 0; i++ < 10;)
   console.log(reg.test("a"));

7 Answers

Removing global g flag will fix your problem.

var re = new RegExp(query, 'gi');

Should be

var re = new RegExp(query, 'i');

You need to set re.lastIndex = 0 because with g flag regex keep track of last match occured, so test will not go to test the same string, for that you need to do re.lastIndex = 0

var query = 'Foo B';
var re = new RegExp(query, 'gi');
var result = [];
result.push(re.test('Foo Bar'));
re.lastIndex=0;
result.push(re.test('Foo Bar'));

console.log(result)

I had the function:

function parseDevName(name) {
  var re = /^([^-]+)-([^-]+)-([^-]+)$/g;
  var match = re.exec(name);
  return match.slice(1,4);
}

var rv = parseDevName("BR-H-01");
rv = parseDevName("BR-H-01");

The first call works. The second call doesn't. The slice operation complains about a null value. I assume this is because of the re.lastIndex. This is strange because I would expect a new RegExp to be allocated each time the function is called and not shared across multiple invocations of my function.

When I changed it to:

var re = new RegExp('^([^-]+)-([^-]+)-([^-]+)$', 'g');

Then I don't get the lastIndex holdover effect. It works as I would expect it to.

Related