38

I know this topic has been thoroughly covered on StackOverflow, but I can't for the life of me get my regular expression to work. So without further repetitive ado ...


This is what I have.

String: <p model='cat'></p>

Regex: .match(/(?:model=')(.*)(?:')/g)

This is what my expression returns: model='cat'

This is what I want: cat


Why isn't my non capture group ignored? Is it that I don't understand what a non-capturing group does? Why isn't my Regex working?

Smern
  • 18,746
  • 21
  • 72
  • 90
vin
  • 823
  • 1
  • 10
  • 15

2 Answers2

48

The entire match will always be group 0, you need to access that specific group (group 1 in this case since the first group is non-capture), you can do it like this:

var str = "<p model='cat'></p>";
var regex = /(?:model=')(.*)(?:')/g
var match = regex.exec(str);
alert(match[1]); // cat

Fiddle

Also, I suppose you are probably wanting several matches within str, you could do that like this:

var str = "<p model='cat'></p><p model='dog'></p><p model='horse'></p>";
var regex = /(?:model=')([^']*)/g
var matches = [];
var match;
while (match = regex.exec(str)) {
  matches.push(match[1]);
}
alert(matches); // cat,dog,horse

Fiddle

JLRishe
  • 99,490
  • 19
  • 131
  • 169
Smern
  • 18,746
  • 21
  • 72
  • 90
  • Strange .. almost like you could see what I was typing .. even the model names are the same. Thanks! – vin Aug 12 '13 at 02:19
  • 2
    That will work without any non-capture, with just `/model='(.*)'/g` and match in `match[1]` – Alex Ivasyuv Jun 29 '17 at 11:35
  • 3
    right, typically no reason to create a non-capture group unless you actually need to do things that require a group – Smern Jun 29 '17 at 12:15
13

A non-capturing group is basically just a non-group ― a way to use parentheses without actually treating that part of the pattern as a group.

It looks like what you're actually looking for are the "match prefix but exclude" group (?<=) and the "match suffix but exclude" group (?=).

Note: This type of group does not seem to be supported in Internet Explorer.

If you use these, you get the desired result:

var str = "<p model='cat'></p><p model='dog'></p><p model='horse'></p>";
var regex = /(?<=model=')[^']*(?=')/g
var matches = str.match(regex);

console.log(matches);
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • I believe this look behind also does not work on Safari, see https://stackoverflow.com/questions/51568821/works-in-chrome-but-breaks-in-safari-invalid-regular-expression-invalid-group – mcnutt Dec 11 '21 at 21:19