Regular Expression Groups: .NET vs JavaScript

Two men in a boxing match.

As a developer, I love solving common string problems with regular expressions. Sure, they are sometimes hard to read, but you can do so much with such a small expression! It is nice that many languages support them, although it sometimes feels like every language creates its own dialect. Let's look at the differences between regular expression groups in .NET and JavaScript.

Named capturing groups are supported by modern JavaScript runtimes, but older browsers and runtimes may not recognize this syntax.

Example string

Things work better with an example, so let's use the following HTML:

<ul>
  <li><a href="https://images.wehkamp.nl/i/wehkamp/16375003_eb_02/1.jpg">Style 1</a></li>
  <li><a href="https://images.wehkamp.nl/i/wehkamp/16374993_eb_02/2.jpg">Style 2</a></li>
  <li><a href="https://images.wehkamp.nl/i/wehkamp/16374973_eb_01/3.jpg">Style 3</a></li>
</ul>

We'll replace each link in this HTML snippet with a linked image, using the link text for the title and alt attributes. This isn't intended to be a general-purpose HTML parser.

.NET: Regex replace

In .NET, we use the Regex class. Let's assume the HTML code is in the variable input:

var input = "{{the html code}}";
var regex = new System.Text.RegularExpressions.Regex("<a href=\"(.*?)\">(.*?)</a>");
var replacement = "<a href=\"$1\"><img src=\"$1\" alt=\"$2\" title=\"$2\" /></a>";
var output = regex.Replace(input, replacement);

JavaScript: RegExp replace

In JavaScript, the regular expression class is called RegExp. We will use the shorter literal notation. Again, let's assume the HTML code is in the input variable:

var input = "{{the html code}}";
var regex = /<a href="(.*?)">(.*?)<\/a>/g;
var replacement = '<a href="$1"><img src="$1" alt="$2" title="$2" /></a>';
var output = input.replace(regex, replacement);

So... what's the difference? Named groups?

There isn't much difference when you stick to the regular expression syntax supported by most engines. But what about named groups? In .NET, you can give groups a name and reference those names in the replacement string. They are used quite frequently by .NET developers! The code looks like this:

var input = "{{the html code}}";
var regex = new System.Text.RegularExpressions.Regex("<a href=\"(?<link>.*?)\">(?<text>.*?)</a>");
var replacement = "<a href=\"${link}\"><img src=\"${link}\" alt=\"${text}\" title=\"${text}\" /></a>";
var output = regex.Replace(input, replacement);

Can we use them in JavaScript? Sure!

var input = "{{the html code}}";
var regex = /<a href="(?<link>.*?)">(?<text>.*?)<\/a>/g
var replacement = '<a href="$<link>"><img src="$<link>" alt="$<text>" title="$<text>" /></a>';
var output = input.replace(regex, replacement);

Instead of ${name}, JavaScript uses $<name> in the replacement string.

One difference: explicitly numbered groups

I found one small but interesting difference: .NET lets you assign explicit numbers to capturing groups. In our first .NET example, the first group was available as $1 and the second as $2. By default, these numbers follow the order of the opening parentheses. .NET also allows you to assign these numbers explicitly:

var input = "{{the html code}}";
var regex = new System.Text.RegularExpressions.Regex("<a href=\"(?<2>.*?)\">(?<1>.*?)</a>");
var replacement = "<a href=\"$2\"><img src=\"$2\" alt=\"$1\" title=\"$1\" /></a>";
var output = regex.Replace(input, replacement);

Here, the link is explicitly assigned to group 2, while the link text is assigned to group 1. JavaScript does not support numeric group names, so its numbered captures always follow the order of the opening parentheses.

If you only need parentheses for grouping and don't want to capture their contents, both .NET and JavaScript support non-capturing groups using (?:...).

Although explicitly numbered groups are valid in .NET, I would avoid them in most code. Descriptive group names are easier to understand and maintain.

Final thoughts

JavaScript and .NET are remarkably similar when it comes to regular expression groups. Who would have thought?

The original article was written in 2010. It used a specific (?<1>.*?) group, which caused the problem I was trying to explain. When I revisited the article ten years later, I discovered what was really happening and decided to rewrite it. It turns out that JavaScript and .NET regular expressions aren't so different after all.

I have to say: after all these years, I still love regular expressions!

Improvements

  • rewrote the article using the latest JavaScript code and .NET Core 3.1.
  • initial article.
      1. Kees C. Bakker says:

        Okay… you got me… I’m testing comments on my blog :P

      2. Kees C. Bakker says:

        Hope it is not annoying!

    1. Kees C. Bakker says:

      Some people would call it link-spamming!

expand_less brightness_auto