Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RegExp.exec() returns NULL sporadically

I am seriously going crazy over this and I've already spent an unproportionate amount of time on trying to figure out what's going on here. So please give me a hand =)

I need to do some RegExp matching of strings in JavaScript. Unfortunately it behaves very strangely. This code:

var rx = /(cat|dog)/gi; var w = new Array("I have a cat and a dog too.", "There once was a dog and a cat.", "I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.");  for (var i in w) {     var m = null;     m = rx.exec(w[i]);     if(m){         document.writeln("<pre>" + i + "\nINPUT: " + w[i] + "\nMATCHES: " + m.slice(1) + "</pre>");     }else{         document.writeln("<pre>" + i + "\n'" + w[i] + "' FAILED.</pre>");     } } 

Returns "cat" and "dog" for the first two elements, as it should be, but then some exec()-calls start returning null. I don't understand why.

I posted a Fiddle here, where you can run and edit the code.

And so far I've tried this in Chrome and Firefox.

like image 423
cpak Avatar asked Jan 18 '11 13:01

cpak


People also ask

What does regex exec return?

JavaScript RegExp exec() The exec() method tests for a match in a string. If it finds a match, it returns a result array, otherwise it returns null.

Can regex match return null?

match(regexp) finds matches for regexp in the string str . If the regexp has flag g , then it returns an array of all matches as strings, without capturing groups and other details. If there are no matches, no matter if there's flag g or not, null is returned.


2 Answers

Oh, here it is. Because you're defining your regex global, it matches first cat, and on the second pass of the loop dog. So, basically you just need to reset your regex (it's internal pointer) as well. Cf. this:

var w = new Array("I have a cat and a dog too.", "I have a cat and a dog too.", "I have a cat and a dog too.", "I have a cat and a dog too.");  for (var i in w) {     var rx = /(cat|dog)/gi;     var m = null;     m = rx.exec(w[i]);     if(m){         document.writeln("<p>" + i + "<br/>INPUT: " + w[i] + "<br/>MATCHES: " + w[i].length + "</p>");     }else{         document.writeln("<p><b>" + i + "<br/>'" + w[i] + "' FAILED.</b><br/>" + w[i].length + "</p>");     }     document.writeln(m); } 
like image 133
SilentGhost Avatar answered Sep 21 '22 13:09

SilentGhost


The regex object has a property lastIndex which is updated when you run exec. So when you exec the regex on e.g. "I have a cat and a dog too.", lastIndex is set to 12. The next time you run exec on the same regex object, it starts looking from index 12. So you have to reset the lastIndex property between each run.

like image 37
Frode Avatar answered Sep 20 '22 13:09

Frode