Prompt template · Data
Regex prompt: build a regular expression from examples
Build a regex for your flavour from strings that should and shouldn’t match, with an explanation and tests. Free to copy, or open it in the prompt builder to fill the variables and get the exact API request.
266 tokens unfilled · 358 with the example below · o200k_base (GPT-4o and later)
Template
The prompt
Paste this into a chat window and replace each {{variable}}, or open it in the prompt builder to fill them in a form. Sections are marked with XML tags, which every major model reads well.
You write correct, readable regular expressions and explain them plainly.
<context>
Strings that must match:
<should_match>
{{should_match}}
</should_match>
Strings that must not match:
<should_not_match>
{{should_not_match}}
</should_not_match>
</context>
<constraints>
- Use only syntax that {{flavour}} supports. Don’t use lookbehind, possessive quantifiers or named groups unless that flavour has them.
- Anchor the pattern if it should match whole strings.
- Avoid patterns that can backtrack catastrophically, such as nested quantifiers on overlapping groups.
- Prefer readable over clever. If the regex gets long, give a commented, verbose version too, if the flavour supports one.
- Check each example against the pattern and report any you are unsure about.
</constraints>
<output_format>
1. The pattern, in a code block, exactly as it would appear in {{flavour}} code.
2. A short explanation of each part.
3. A table of every example with “matches” or “doesn’t match”.
4. Two or three edge cases worth adding as tests.
</output_format>
<task>
Write a regular expression for {{flavour}} that {{goal}}. It must match every string in the first list and none in the second.
</task>For an API call: system prompt and user message
With a system prompt, the role, constraints and output format stay fixed across calls (and can be cached), while the context and task go in the user message.
You write correct, readable regular expressions and explain them plainly.
<constraints>
- Use only syntax that {{flavour}} supports. Don’t use lookbehind, possessive quantifiers or named groups unless that flavour has them.
- Anchor the pattern if it should match whole strings.
- Avoid patterns that can backtrack catastrophically, such as nested quantifiers on overlapping groups.
- Prefer readable over clever. If the regex gets long, give a commented, verbose version too, if the flavour supports one.
- Check each example against the pattern and report any you are unsure about.
</constraints>
<output_format>
1. The pattern, in a code block, exactly as it would appear in {{flavour}} code.
2. A short explanation of each part.
3. A table of every example with “matches” or “doesn’t match”.
4. Two or three edge cases worth adding as tests.
</output_format><context>
Strings that must match:
<should_match>
{{should_match}}
</should_match>
Strings that must not match:
<should_not_match>
{{should_not_match}}
</should_not_match>
</context>
<task>
Write a regular expression for {{flavour}} that {{goal}}. It must match every string in the first list and none in the second.
</task>Variables
What to put in each variable
- {{should_match}}
- Real strings that must match, one per line. Include the awkward ones.
- {{should_not_match}}
- Near misses that must not match, one per line. These define the edges better than any description.
- {{flavour}}
- The regex engine, such as JavaScript (ES2024), Python re, PCRE2, Go RE2 or .NET. They differ in lookbehind, Unicode and escaping.
- {{goal}}
- What the pattern is for, such as “matches a UK postcode” or “captures the version number from a log line”.
Use
When to use it
Use it for validation patterns, log parsing and search-and-replace jobs, especially when you have real examples to hand. The examples are the specification: a regex is only as correct as the cases you test it against.
Run the result against your examples in your actual language before using it. Models are often right but can misjudge a match, and the flavour differences (Go’s RE2 has no lookbehind, for instance) only show up when the pattern runs.
Structure
Why it’s structured this way
Examples on both sides define the pattern far better than prose. “Match an email” means something different to everyone; a list of strings that must and mustn’t match is unambiguous. The near misses are especially valuable, because they are where loose patterns fail.
The flavour is repeated in the task and constraints because it decides which syntax is legal. A lookbehind that works in JavaScript fails to compile in Go, and Python’s re.VERBOSE mode has no direct JavaScript equivalent.
The match table asks the model to check its own work against every example, and to say where it is unsure. The rule against catastrophic backtracking guards against a real production risk: a regex that hangs on certain input can take a service down.
Example
A filled-in example
- {{should_match}}
1.4.0 0.0.1 10.20.30 2.0.0-beta.3 1.0.0-rc.1
- {{should_not_match}}
1.4 01.2.3 1.2.3.4 v1.2.3 1.2.3-
- {{flavour}}
JavaScript (ES2024)
- {{goal}}
matches a semantic version such as 1.4.0 or 2.0.0-beta.3, as a whole string
What to look for. The near misses do the work here: 01.2.3 rules out leading zeros and 1.2.3- rules out an empty pre-release. A good answer uses ^ and $ anchors and (0|[1-9]\d*) for each number, and its match table should show all ten examples correctly.
The complete filled-in prompt (358 tokens)
You write correct, readable regular expressions and explain them plainly.
<context>
Strings that must match:
<should_match>
1.4.0
0.0.1
10.20.30
2.0.0-beta.3
1.0.0-rc.1
</should_match>
Strings that must not match:
<should_not_match>
1.4
01.2.3
1.2.3.4
v1.2.3
1.2.3-
</should_not_match>
</context>
<constraints>
- Use only syntax that JavaScript (ES2024) supports. Don’t use lookbehind, possessive quantifiers or named groups unless that flavour has them.
- Anchor the pattern if it should match whole strings.
- Avoid patterns that can backtrack catastrophically, such as nested quantifiers on overlapping groups.
- Prefer readable over clever. If the regex gets long, give a commented, verbose version too, if the flavour supports one.
- Check each example against the pattern and report any you are unsure about.
</constraints>
<output_format>
1. The pattern, in a code block, exactly as it would appear in JavaScript (ES2024) code.
2. A short explanation of each part.
3. A table of every example with “matches” or “doesn’t match”.
4. Two or three edge cases worth adding as tests.
</output_format>
<task>
Write a regular expression for JavaScript (ES2024) that matches a semantic version such as 1.4.0 or 2.0.0-beta.3, as a whole string. It must match every string in the first list and none in the second.
</task>Models
Tips by model family
- All models
Paste the pattern into your test suite with the example strings as cases. That turns the model’s match table into a check you actually run.
- OpenAI GPT
Reasoning models handle the self-check step well without extra prompting. OpenAI advises against adding “think step by step” to them; the table in the format line is enough.
- Claude
Anthropic suggests asking Claude to verify its answer against test criteria before finishing, and the match table does that. On Claude Opus 5, Anthropic says such checks can cause over-verification, so drop the last constraint if responses get slow.
Related
Related templates and tools
- Extract structured JSONPull fields from emails, documents or pages into a fixed JSON shape, with null instead of guesses.
- Clean and normalise dataNormalise messy records to your rules, flag the rows it can’t fix, and never drop or invent data.
- Write unit testsTests for normal cases, edge cases and errors in your framework, focused on behaviour rather than implementation.
Edited the template? Compare your version with this one in the prompt diff, and count it for your model with the token counter. Browse all 29 prompt templates.