Have a regex:
.*?
(rule1|rule2)
(?:(rule1|rule2)|[^}])*
(It's designed to parse CSS files, and the 'rules' are generated by JS.)
When I try this in IE, all works as it should. Ditto when I try it in RegexBuddy or The Regex Coach.
But when I try it in Firefox or Chrome, the results are missing values.
Can anyone please explain what the real browsers are thinking, or how I can achieve results similar to IE's?
To see this in action, load up a page that gives you interactive testing, such as the W3Schools try-it-out editor.
Here's the source that can be pasted in: http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_regexp_exec
<html>
<body>
<script type="text/javascript">
var str="#rot { rule1; rule2; }";
var patt=/.*?(rule1|rule2)(?:(rule1|rule2)|[^}])*/i;
var result=patt.exec(str);
for(var i = 0; i < 3; i++) document.write(i+": " + result[i]+"<br>");
</script>
</body>
</html>
Here is the output in IE:
0: #rot { rule1; rule2;
1: rule1
2: rule2
Here is the output in Firefox and Chrome:
0: #rot { rule1; rule2;
1: rule1
2: undefined
When I try the same using string.match, I get back an array of undefined in all browsers, including IE.
var str="#rot { rule2; rule1; rule2; }";
var patt=/.*?(rule1|rule2)(?:(rule1|rule2)|[^}])*/gi;
var result=str.match(patt);
for(var i = 0; i < 5; i++) document.write(i+": "+result[i]+"<br>");
As far as I can tell, the issue is the last non-capturing parenthesis.
When I remove them, the results are consistent cross browser - and match() gets results.
However, it does capture from the last parenthesis, in all browsers, in the following example:
<script>
var str="#rot { rule1; rule2 }";
var patt=/.*?(rule1|rule2)(?:(rule1 |rule2 )|[^}])*/gi;
var result=patt.exec(str);
for(var i =0; i < 3; i++) document.write(i+": "+result[i]+"<br>");
</script>
Notice that I've added a space to the patterns in the second regex.
The same applies if I add any negative character to the strings in the second regex:
var patt=/.*?(rule1|rule2)(?:(rule1[^1]|rule2[^1])|[^}])*/gi;
What the expletive is going on?!
All other strings that I've tried result in the first set of non-catches.
Any help is greatly appreciated!
EDIT:
The code has been shortened, and many hours of research put in, on Mathhew's advice.
The title has been changed to make the thread easier to find.
I have marked Mathew's answer as correct, as it is well researched and described.
My answer below (written before Mathew revised his) states the logic in simpler and more direct terms.