Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Named capturing groups in JavaScript regex?

People also ask

What is capturing group in regex Javascript?

A part of a pattern can be enclosed in parentheses (...) . This is called a “capturing group”. That has two effects: It allows to get a part of the match as a separate item in the result array.

How do I reference a capture group in regex?

If your regular expression has named capturing groups, then you should use named backreferences to them in the replacement text. The regex (?' name'group) has one group called “name”. You can reference this group with ${name} in the JGsoft applications, Delphi, .

Can I use named capturing groups?

Mixing named and numbered capturing groups is not recommended because flavors are inconsistent in how the groups are numbered. If a group doesn't need to have a name, make it non-capturing using the (?:group) syntax. In . NET you can make all unnamed groups non-capturing by setting RegexOptions.

What is named group in Javascript?

Named capturing group: Matches "x" and stores it on the groups property of the returned matches under the name specified by <Name> . The angle brackets ( < and > ) are required for group name.


ECMAScript 2018 introduces named capturing groups into JavaScript regexes.

Example:

  const auth = 'Bearer AUTHORIZATION_TOKEN'
  const { groups: { token } } = /Bearer (?<token>[^ $]*)/.exec(auth)
  console.log(token) // "Prints AUTHORIZATION_TOKEN"

If you need to support older browsers, you can do everything with normal (numbered) capturing groups that you can do with named capturing groups, you just need to keep track of the numbers - which may be cumbersome if the order of capturing group in your regex changes.

There are only two "structural" advantages of named capturing groups I can think of:

  1. In some regex flavors (.NET and JGSoft, as far as I know), you can use the same name for different groups in your regex (see here for an example where this matters). But most regex flavors do not support this functionality anyway.

  2. If you need to refer to numbered capturing groups in a situation where they are surrounded by digits, you can get a problem. Let's say you want to add a zero to a digit and therefore want to replace (\d) with $10. In JavaScript, this will work (as long as you have fewer than 10 capturing group in your regex), but Perl will think you're looking for backreference number 10 instead of number 1, followed by a 0. In Perl, you can use ${1}0 in this case.

Other than that, named capturing groups are just "syntactic sugar". It helps to use capturing groups only when you really need them and to use non-capturing groups (?:...) in all other circumstances.

The bigger problem (in my opinion) with JavaScript is that it does not support verbose regexes which would make the creation of readable, complex regular expressions a lot easier.

Steve Levithan's XRegExp library solves these problems.


Another possible solution: create an object containing the group names and indexes.

var regex = new RegExp("(.*) (.*)");
var regexGroups = { FirstName: 1, LastName: 2 };

Then, use the object keys to reference the groups:

var m = regex.exec("John Smith");
var f = m[regexGroups.FirstName];

This improves the readability/quality of the code using the results of the regex, but not the readability of the regex itself.


You can use XRegExp, an augmented, extensible, cross-browser implementation of regular expressions, including support for additional syntax, flags, and methods:

  • Adds new regex and replacement text syntax, including comprehensive support for named capture.
  • Adds two new regex flags: s, to make dot match all characters (aka dotall or singleline mode), and x, for free-spacing and comments (aka extended mode).
  • Provides a suite of functions and methods that make complex regex processing a breeze.
  • Automagically fixes the most commonly encountered cross-browser inconsistencies in regex behavior and syntax.
  • Lets you easily create and use plugins that add new syntax and flags to XRegExp's regular expression language.

In ES6 you can use array destructuring to catch your groups:

let text = '27 months';
let regex = /(\d+)\s*(days?|months?|years?)/;
let [, count, unit] = regex.exec(text) || [];

// count === '27'
// unit === 'months'

Notice:

  • the first comma in the last let skips the first value of the resulting array, which is the whole matched string
  • the || [] after .exec() will prevent a destructuring error when there are no matches (because .exec() will return null)