Skip to main content
v3.2.0Open source · MIT · .NET 8 / 10 · .NET Standard 2.1

Regular expressions you can read, prove and ship.

Build .NET regexes from readable, immutable building blocks. Prove two patterns equivalent, catch ReDoS before it ships, test with generated data, and run the same pattern in JavaScript, JSON Schema or your database.

dotnet add package Masterly.FluentRegex
Try it in the playground
InvoiceNumbers.cs
Pattern invoice = Pattern.With
.WordBoundary
.Literal("INV-")
.NamedGroup("year", Pattern.With.Digit.Repeat.Times(4))
.Literal("-")
.NamedGroup("number", Pattern.With.Digit.Repeat.Times(4))
.WordBoundary;

string text = "Paid INV-2024-0001 and INV-2025-0420, not INV-24-1.";
MatchCollection matches = invoice.Matches(text);
Console.WriteLine(invoice.Explain());
OutputReady
  1. invoice.ToString()
    \bINV-(?<year>\d{4})-(?<number>\d{4})\b
  2. invoice.Matches(text)

    Paid INV-2024-0001 and INV-2025-0420, not INV-24-1.

    yearnumbernamed groups

  3. invoice.Explain()
    Pattern: \bINV-(?<year>\d{4})-(?<number>\d{4})\b
    
    Explanation:
      - Word boundary
      - Literal 'I'
      - Literal 'N'
      - Literal 'V'
      - Character '-'
      - Named capturing group 'year'
        - Digit [0-9]
        - Exactly 4 times
        - End of group
      - Character '-'
      - Named capturing group 'number'
        - Digit [0-9]
        - Exactly 4 times
        - End of group
      - Word boundary
0
dependencies in the core package
6
packages, one shared version
5
SQL dialects, plus JavaScript and JSON Schema
.NET Standard 2.1
plus native .NET 8 and .NET 10 builds
Write

Five ways to get a pattern, one Pattern type

Build it, convert it, describe it, learn it or pick it from the library. Whichever way you start, you get the same immutable Pattern that matches, explains, proves and exports.

Compose a pattern from named building blocks. Every call returns a new, immutable pattern. Learn more

Pattern semver = Pattern.With
.StartOfLine
.NamedGroup("major", Pattern.With.Digit.Repeat.OneOrMore)
.Literal(".")
.NamedGroup("minor", Pattern.With.Digit.Repeat.OneOrMore)
.Literal(".")
.NamedGroup("patch", Pattern.With.Digit.Repeat.OneOrMore)
.EndOfLine;

semver.ToString(); // ^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)$
semver.IsMatch("3.1.0"); // true
semver.IsMatch("3.1"); // false
Capabilities

More than a builder

Start with a readable pattern. Then prove it, harden it, test it and take it wherever your data lives, without rewriting it for each place.

Prove two patterns equal

Pattern.Compare decides equivalence, subset and overlap exactly. When two patterns differ, you get the shortest string that tells them apart.

Read the guide
left\d{3}right[0-9]{3}
Relation
ProperSuperset
Shortest counterexample
"00٠"left acceptsright rejects
Both accept
"000"

٠ is an Arabic-Indic zero: \d matches every Unicode decimal digit.

Optimize with proof

Optimize() rewrites cat|car|cab to ca[trb], then proves the result matches exactly the same strings.

Read the guide

Catch ReDoS early

AnalyzeSafety() finds repetitions that backtrack exponentially, and can confirm each one with a timed attack.

Read the guide

Typed extraction

Extract<T>() binds named groups straight onto records and classes, converting each value to its member type.

Read the guide

Checked as you type

The bundled source generator and analyzers flag invalid patterns, ReDoS risks and group-name typos at build time.

Read the guide

Coverage and test data

MeasureCoverage() shows the branches your tests never hit. GenerateMatching() and GenerateNonMatching() produce samples and near misses.

Read the guide

Run it in the database

The same pattern becomes each database’s own regex, with the exact .NET meaning. The EF Core package runs it inside LINQ queries and CHECK constraints.

Read the guide
ToSqlCondition("Sku", flavor) for ^[A-Z]{3}-[0-9]{4}$
DialectSQL
PostgreSQLSku ~ '\A[A-Z]{3}-[0-9]{4}(?=\n?\Z)'
MySQLREGEXP_LIKE(Sku, '(?-i)\\A[A-Z]{3}-[0-9]{4}(?=\\n?\\z)')
SQL Server 2025REGEXP_LIKE(Sku, N'\A[A-Z]{3}-[0-9]{4}\n?\z')
SQLiteSku REGEXP '^[A-Z]{3}-[0-9]{4}$'

Trace every match

Trace(input) shows which construct matched which text, or exactly where and why matching failed.

Read the guide

One pattern, every platform

ToJavaScript(), JSON Schema and TypeScript output keep the .NET meaning in browsers and API contracts.

Read the guide

Redact personal data

Redactor.For(...) finds emails, phone numbers and other personal data in text, and masks each with the style you choose.

Read the guide

Write your first readable pattern in five minutes.

The Quick Start builds a pattern, tests it, extracts matches with named groups and explains it. The playground runs every feature in your browser.