regex: grouping matches



~2 min read


313 words

As regular expressions get longer and more complicated capture groups can be nice to organize the different pieces of a match.

For example, I’ve been writing about matching Markdown links recently here and here. So, let’s keep building on that.

Imagine we want to match any string that fits a link in markdown — excluding reference links. So, roughly speaking there will be a pair of brackets followed by a parentheses, [title](link).

One way to write the regex pattern is to determine if there’s a match.

const pattern = /\[[^\]]*\]\([^\)]+\)/
const match = "[title](link)".match(pattern)

In this case, match will be an array with either one or zero elements.

But what if we want to see the different parts of the match too? We can use groups for that. Groups are parts of the pattern that are wrapped in parentheses. Let’s add a few now:

const pattern = /\[([^\]]*)\]\(([^\)]+)\)/
const match = "[title](link)".match(pattern)
["[title](link)", "title", "link"]

Now the array will be three elements long if each part of it matches. This can be useful, but it’s rather declarative. It requires that you know what each returned value refers to.

This is where named groups come in. To name a group we add a title directly inside the group’s opening parenthesis.

const pattern = /\[(?<title>[^\]]*)\]\((?<link>[^\)]+)\)/
const match = "[title](link)".match(pattern)

By naming the groups we’ll still get an array returned, but there will also be a groups property attached to the match object (remember arrays are objects and can have properties). This property will include each of the named groups:

const groups = match.groups
console.log({ groups })
{title: 'test', link: ''}

Not only do named groups help with understanding complicated regular expressions when you return to them later, but they also make using the results of the group easier!

Hi there and thanks for reading! My name's Stephen. I live in Chicago with my wife, Kate, and dog, Finn. Want more? See about and get in touch!