8

The Situation

I have a string that I want to match the same capture group multiple times. I need to be able to get at both matches.

Example Code

var curly = new RegExp("{([a-z0-9]+)}", "gi");
var stringTest = "This is a {test} of my {pattern}";

var matched = curly.exec(stringTest);
console.log(matched);

The Problem

Right now, it only shows the first match, not the second.

JSFiddle Link

http://jsfiddle.net/npp8jg39/

Jake
  • 4,014
  • 8
  • 36
  • 54

4 Answers4

9

Try this:

    var curly = /{([a-z0-9]+)}/gi,
        stringTest = "This is a {test} of my {pattern}",
        matched;
    while(matched = curly.exec(stringTest))
        console.log(matched);
user10089632
  • 5,216
  • 1
  • 26
  • 34
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • Note that the regexp must be specified in a separate variable. `while (/{[a-z0-9]+)}/gi.exec(stringTest))` doesnot shift the index and does not end well. – dr jerry Dec 29 '19 at 15:49
4

Normally this is done by the RegExp.exec method but you know it's convoluted. Everytime I need to use it i have to look up to remember this stateful operation. It's like you need a state monad or something :)

Anyways. In recent JS engines there is this String.matchAll() which does the same thing in a much sane fashion by returning an iterator object.

var curly = new RegExp("{([a-z0-9]+)}", "gi");
var stringTest = "This is a {test} of my {pattern}";

var matches = [...stringTest.matchAll(curly)];
console.log(matches);

If you need only the capture groups then just map the above result. Let's use Array.from() this time.

var curly = new RegExp("{([a-z0-9]+)}", "gi");
var stringTest = "This is a {test} of my {pattern}";

var matches = Array.from(stringTest.matchAll(curly), m => m[1]);
console.log(matches);
Redu
  • 25,060
  • 6
  • 56
  • 76
2

The exec method must be used in a while loop if you want to treat several results. See the MDN Documentation.

Casimir et Hippolyte
  • 88,009
  • 5
  • 94
  • 125
2

Strings in JavaScript have a match method - you can use this to match all instances of a regular expression, returned as an array:

stringTest.match(curly);

This will return an array of matches:

> ["{test}", "{pattern}"]

To pull the inner values, you can use substr:

var arr = stringTest.match(curly);

arr[0] = arr[0].substr(1, arr[0].length - 2);
> "test"

Or to convert the entire array:

for (var i = 0; i < arr.length; i++)
    arr[i] = arr[i].substr(1, arr[i].length - 2);
> ["test", "pattern"]
James Donnelly
  • 126,410
  • 34
  • 208
  • 218
  • I need to be able to get the string inside the capture group, though. Like "test" and "pattern". – Jake Oct 15 '14 at 21:31
  • +1, could you also include the code to do it with an `exec` loop, for iterative processing? – salezica Oct 15 '14 at 21:32