Hand-splicing alternations breaks the moment rules overlap. Intersect, subtract or union patterns as sets and get back one clean pattern, ready for the next call.
Each card calls the real API. Edit the patterns and compute. No signup.
| Operation | Notation | Answers | Returns |
|---|---|---|---|
| intersection | A ∩ B | Strings matching all of the patterns. | term |
| union | A ∪ B | Strings matching any of the patterns. | term |
| difference | A ∖ B | Strings in A but not in B. | term |
| complement | ∁A | Every string the pattern does not match. | term |
| concatenation | A · B | Patterns joined in sequence. | term |
| repeat | A{n,m} | The pattern repeated n to m times. | term |
| determinize | dfa(A) | The same language as a deterministic FAIR, for a stable string order. | term |
Every operation above through the official client. The API is plain REST underneath, so any HTTP client works too.
import { RegexSolverClient, Term } from 'regexsolver';
const client = new RegexSolverClient({ apiToken: 'REGEXSOLVER_API_TOKEN' });
// What do both firewalls accept? Intersect them and read the result.
const both = await client.intersection(
Term.regex("/api/v[12]/.*"),
Term.regex(".*/users/[0-9]+"),
);
await client.getPattern(both);
// "/api/v[12]/(.*/)?users/[0-9]+"
// Drop gif support from an allowlist: subtract one rule from another
const noGif = await client.difference(
Term.regex(".*\.(jpe?g|png|gif)"),
Term.regex(".*\.gif"),
);
await client.getPattern(noGif);
// ".*\.(jpe?|pn)g"
// Everything the validator rejects
const rejected = await client.complement(noGif);
// Results are terms: chain them without re-parsing.
// A term and its complement can never overlap:
await client.isEmpty(await client.intersection(noGif, rejected));
// true