liveBook · Manning

Regex grouping

As explained in Secrets of the JavaScript Ninja, Second Edition

A regular-expression subgroup whose matched text is recorded for later access or reference.

A regular expression can tell you whether a string matches. Parentheses make it more useful: they group terms into one unit and record the text matched by that group as a capture. For example, /(ab)+/ matches one or more consecutive occurrences of ab because + applies to the whole group. section 10.2.2

Extract a CSS transform value

Suppose an element has transform: translateY(15px), and you need the embedded value. Matching its transform string against /translateY\(([^\)]+)\)/ puts the full match, translateY(15px), at index 0 and the capture, 15px, at index 1. Check that a match exists before reading [1]: match returns null when nothing matches. section 10.4.1

Listing 10.4. A simple function for capturing an embedded value
<div id="square" style="transform:translateY(15px);"></div>            #A
<script>
  function getTranslateY(elem){
    const transformValue = elem.style.transform;
    if(transformValue){
      const match = transformValue.match(/translateY\(([^\)]+)\)/);    #B
      return match ? match[1] : "";                                    #B
    }

    return "";
  }

  const square = document.getElementById("square");

  assert(getTranslateY(square) === "15px", 
         "We've extracted the translateY value");
</script>

The function reads an element’s transform, captures its translateY value, and returns an empty string if the property or match is absent. section 10.4.1

Choose the API according to what you need from the match:

  • For one match, String.match returns the full match followed by its captures. With the g flag, it instead returns the full matches without their individual captures. section 10.4.2
  • For captures from every global match, repeatedly call RegExp.exec; each call advances to the next match and returns its captures. section 10.4.2
  • Within a regex, \1, \2, and so on refer back to earlier captures. The pattern /^([dtn])a\1/ requires the character after a to repeat the first captured character. section 10.2.2

Use a capture during replacement

"border-bottom-width".replace(/-(\w)/g, (all, letter) => letter.toUpperCase()) produces "borderBottomWidth". For each match, the replacement function receives the full match and then the captured letter; it returns the text to substitute. section 10.5

How Secrets of the JavaScript Ninja, Second Edition covers it

How deep it goes
Works through capture positions and the different results of local match, global match, and repeated exec calls.
Examples
Uses CSS translateY extraction, HTML-tag matches, and dashed-string camel casing.
What it assumes
Assumes familiarity with JavaScript strings while revisiting regex terms, operators, and grouping rather than requiring an exhaustive regex background.
What you can do after
Apply captures via String.match, RegExp.exec, or String.replace to extract or transform matched text.
How it connects
Connects regex quantifiers and backreferences with String.match, RegExp.exec, and String.replace.

Also explained in

Compare how 6 books explain regex grouping →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Secrets of the JavaScript Ninja, Second Edition. The section links point to the parts of the book it draws on.