Published at
Updated at
Reading time
This post is part of my Today I learned series in which I share all my web development learnings.

It's regular expression time again. ๐ŸŽ‰ I don't remember where I saw the following discovery, but I'm astonished that I didn't know about non-capturing groups after years of using regular expressions.

If you already know what non-capturing groups in regular expressions are, here's the syntax: it's (?:) as in /(?:non-caputuring group)/.

To understand how non-capturing groups work, let's look at an example highlighting the well-known capturing groups.

// a regular expression including three capture groups
const regex = /(Jane|John|Alison)\s(.*?)\s(Smith|Smuth)/;

The regular expression above defines that I'm looking for a very particular name combination. The name should begin with Jane, John or Alison, end with Smith or Smuth but include a middle name between the first and last name.

const result = regex.exec('Jane Isabell Smith');
console.log(result[0]); // 'Jane Isabell Smith'
console.log(result[1]); // 'Jane'
console.log(result[2]); // 'Isabell'
console.log(result[3]); // 'Smith'

Run the regular expression's exec method to test if a string is matching the expression. If the string matches the expression, the return value is an array holding all the specific information, otherwise exec returns null.

The array includes the full matching string at index 0 followed by the defined groups (1, 2, etc.). In this example, the array holds the character sequences matching the three defined capturing groups. Even though you're only interested in the middle name represented by the entry at index 2 you have to deal with the data for all groups.

There's nothing particularly wrong with this approach, but to extract the desired middle name, you have to remember and go back to the original regular expression because the result includes several irrelevant values (1 and 3).

It turns out that you can define non-capturing groups that are not included in the result!

// a regular expression with two non-capturing groups
// and one capturing group
const regex = /(?:Jane|John|Alison)\s(.*?)\s(?:Smith|Smuth)/;
const result = regex.exec('Jane Isabell Smith');
console.log(result[0]); // 'Jane Isabell Smith'
console.log(result[1]); // 'Isabell'

const notMatchingResult = regex.exec('nope');
console.log(notMatchingResult); // null

Use the (?:) syntax to match non-capturing groups in your strings. Non-capturing groups are excluded from the result.

When dealing with complex regular expressions, this feature is beneficial because it simplifies the result handling! ๐ŸŽ‰

Edited: As Dave Newson pointed out, there are also named capture groups on their way! The "group future" looks bright!

Was this TIL post helpful?
Yes? Cool! You might want to check out Web Weekly for more quick learnings. The last edition went out 4 days ago.
Stefan standing in the park in front of a green background

About Stefan Judis

Frontend nerd with over ten years of experience, freelance dev, "Today I Learned" blogger, conference speaker, and Open Source maintainer.

Related Topics

Related Articles