Appearance
Readable Regular Expressions
When to use
Use this when a regex is too complex to read as a single literal. The regexr package provides a tagged template function that lets you build regular expressions from named, composable pieces — no double-escaping, no builder classes, just template literals and interpolation.
The pattern
Use the re tagged template to write regex fragments as template strings. Interpolate RegExp instances or other re-tagged strings to compose larger patterns. Use the escape helper to safely include user input.
Composing patterns
Name each part of a complex regex, then interpolate them into a final pattern. Each re-tagged template returns a RegExp that can be interpolated into another re template or passed to new RegExp() to add flags:
javascript
import { r as re } from "regexr";
const useDBStatement = re`^USE .*;$`;
const createDBStatement = re`^CREATE DATABASE .*;$`;
const pattern = re`${useDBStatement}|${createDBStatement}`;
const regex = new RegExp(pattern, "gm");Breaking down a complex pattern
Give each piece a descriptive name. The template literal reads like documentation — each variable explains what that part of the regex matches:
javascript
import { r as re } from "regexr";
const year = re`\d{4}`;
const month = re`\d{2}`;
const day = re`\d{2}`;
const date = re`^${year}-${month}-${day}$`;
date.test("2025-01-15"); // true
date.test("25-1-5"); // falseMixing regex literals and tagged templates
Interpolate existing RegExp instances directly into re-tagged templates. This lets you reuse patterns defined as literals:
javascript
import { r as re } from "regexr";
const protocol = /https?/;
const domain = /[\w-]+(\.[\w-]+)+/;
const url = re`^${protocol}://${domain}$`;
url.test("https://example.com"); // trueEscaping user input
Use the escape helper to escape strings that may contain regex-special characters so they match literally:
javascript
import { r as re, escape } from "regexr";
const searchTerm = "$10.00 (USD)";
const pattern = re`value: ${escape(searchTerm)}`;
// matches literal "$10.00 (USD)" instead of
// treating $, ., and () as regex operatorsAdding flags
The re tag returns a RegExp without flags. Wrap it in new RegExp() to add flags like g, m, or i:
javascript
import { r as re } from "regexr";
const comment = re`^\s*#.*$`;
const allComments = new RegExp(comment, "gm");
const text = `
# comment one
code here
# comment two
`;
text.match(allComments);
// [" # comment one", " # comment two"]Trade-offs
- Pros: No double-escaping. Named pieces are self-documenting. Composes naturally through template interpolation. The
escape()helper safely escapes user input. Tiny dependency (regexron npm). - Cons: Requires an npm dependency. The
retag returns a flaglessRegExp— wrap innew RegExp()when you need flags likegorm. - Versus a builder class: A fluent builder API (
.digit().repeat()) adds methods for every regex feature and requires learning a custom DSL. Tagged templates use standard regex syntax directly, which is more concise and familiar. - Versus regex literals: Use a literal (
/pattern/) when the pattern is short, static, and easy to read at a glance. Userewhen the pattern is long enough to benefit from named parts.