C# Regex Groups

Summary: in this tutorial, you will learn about capturing groups and how to use the C# Regex Groups property to get the matches.

Introduction to the C# Regex Groups

Suppose you want to match a route that starts with posts followed by a forward slash / and an id like this:

posts/idCode language: C# (cs)

To do that, you may come up with the following regular expression pattern:

posts/\d+

And the following program illustrates how you would use that pattern to match the route:

using System.Text.RegularExpressions;
using static System.Console;


var route = "posts/100";
var pattern = @"posts/\d+";

var match = Regex.Match(route, pattern);

WriteLine(match.Value);Code language: C# (cs)

Output:

posts/100Code language: C# (cs)

The pattern posts/\d+ matches the posts/ characters and is followed by one or more digits. It returns the result as expected.

Now, you want to extract the id from the route, which is 100 in this case. To do that, you can use something called capturing group in regular expressions.

By definition, a capturing group allows you to capture a portion of the matched text. To create a capturing group, you define a subpattern within the overall pattern and closed it within parentheses.

In our example, we can create a subpattern like this:

posts/(\d+)Code language: C# (cs)

This (\d+) is a capturing group and \d+ is a subpattern.

If the matches are found, you can access the groups via the Groups property of the Match object. The type of Groups is the GroupCollection type which is a collection of Group objects.

The first element in the Groups collection is the whole match which is posts/100 in this example and the next elements are the matched text of the capturing groups.

The following example uses the capturing group to exact the id from the route posts/100:

using System.Text.RegularExpressions;
using static System.Console;

var route = "posts/100";
var pattern = @"posts/(\d+)";

var match = Regex.Match(route, pattern);

if (match.Success)
{
    foreach (var group in match.Groups)
    {
        WriteLine(group);
    }
}Code language: C# (cs)

Output:

posts/100
100Code language: C# (cs)

A regular expression may contain multiple capturing groups. For example:

using System.Text.RegularExpressions;
using static System.Console;


// posts/year/month/date format
var route = "posts/2023/12/31";

var pattern = @"posts/(\d{4})/(\d{2})/(\d{2})";

var match = Regex.Match(route, pattern);

if (match.Success)
{
    foreach (var group in match.Groups)
    {
        WriteLine(group);
    }
}Code language: C# (cs)

Output:

posts/2023/12/31
2023
12
31Code language: C# (cs)

In this example, we have three capturing groups for year, month, and date in the route. The output shows four groups, which include the whole match.

Named capturing groups

By using the Groups property, you can iterate the groups or access a group by index. For example, the Groups[1] should return the year which is 2023:

using System;
using System.Text.RegularExpressions;
using static System.Console;


// posts/year/month/date format
var route = "posts/2023/12/31";

var pattern = @"posts/(\d{4})/(\d{2})/(\d{2})";

var match = Regex.Match(route, pattern);

if (match.Success && match.Groups.Count == 4)
{
    var year = match.Groups[1];
    var month = match.Groups[2];
    var day = match.Groups[3];
    WriteLine($"{year}/{month}/{day}");
}Code language: JavaScript (javascript)

It’s more explicit to assign a name to each capturing in the regular expression so that we can access each group by name rather than by index.

To do that, you can use the following syntax:

(?<name>rule)Code language: C# (cs)

In this syntax:

  • The () denotes a capturing group.
  • The ?<name> specifies the capturing group’s name.
  • The rule is a subpattern.

To access the matched value, you look it up in the Groups property by group name like this:

Groups["name"]Code language: C# (cs)

For example:

using System.Text.RegularExpressions;
using static System.Console;


// posts/year/month/date format
var route = "posts/2023/12/31";

var pattern = @"posts/(?<year>\d{4})/(?<month>\d{2})/(?<day>\d{2})";

var match = Regex.Match(route, pattern);

if (match.Success)
{
    var year = match.Groups["year"];
    var month = match.Groups["month"];
    var day = match.Groups["day"];
    WriteLine($"{year}/{month}/{day}");

}Code language: C# (cs)

Output:

2023/12/31Code language: C# (cs)

Summary

  • Place a pattern inside the parentheses () to create a capturing group.
  • Use the Match.Groups property to access the groups. The first group is the whole match and the next ones are the matched groups.
  • Use the (?<name>rule) syntax to assign a name to a capturing group and access its matched value using Groups["name"].
Was this tutorial helpful ?