JavaScript RegExp Groups


Example

JavaScript supports several types of group in it's Regular Expressions, capture groups, non-capture groups and look-aheads. Currently, there is no look-behind support.

Capture

Sometimes the desired match relies on it's context. This means a simple RegExp will over-find the piece of the String that is of interest, so the solution is to write a capture group (pattern). The captured data can then be referenced as...

  • String replacement "$n" where n is the n th capture group (starting from 1)
  • The n th argument in a callback function
  • If the RegExp is not flagged g, the n+1 th item in a returned str.match Array
  • If the RegExp is flagged g, str.match discards captures, use re.exec instead

Say there is a String where all + signs need to be replaced with a space, but only if they follow a letter character. This means a simple match would include that letter character and it would also be removed. Capturing it is the solution as it means the matched letter can be preserved.

let str = "aa+b+cc+1+2",
    re = /([a-z])\+/g;

// String replacement
str.replace(re, '$1 '); // "aa b cc 1+2"
// Function replacement
str.replace(re, (m, $1) => $1 + ' '); // "aa b cc 1+2"

Non-Capture

Using the form (?:pattern), these work in a similar way to capture groups, except they do not store the contents of the group after the match.

They can be particularly useful if other data is being captured which you don't want to move the indices of, but need to do some advanced pattern matching such as an OR

let str = "aa+b+cc+1+2",
    re = /(?:\b|c)([a-z])\+/g;

str.replace(re, '$1 '); // "aa+b c 1+2"

Look-Ahead

If the desired match relies on something which follows it, rather than matching that and capturing it, it is possible to use a look-ahead to test for it but not include it in the match. A positive look-ahead has the form (?=pattern), a negative look-ahead (where the expression match only happens if the look-ahead pattern did not match) has the form (?!pattern)

let str = "aa+b+cc+1+2",
    re = /\+(?=[a-z])/g;

str.replace(re, ' '); // "aa b cc+1+2"