Skip to main content

Build Regex from Examples: Give Samples, Get a Pattern That Fits

Stop writing regex blind. Paste strings that should match and ones that shouldn't, infer a pattern, generalize it safely, then verify the edges before you ship.

Published By Li Lei
#regex #developer-tools #text-processing #tutorial

Build Regex from Examples Instead of Writing It Blind

The slowest way to write a regular expression is to write it. You stare at a sample string, count character positions in your head, guess at quantifiers, run it, watch it miss half the lines, tweak, run again. Twenty minutes later you have \d{5} when the real codes are sometimes four digits.

There's a faster path that I now reach for first: start from the strings themselves. Collect a handful of real examples of what you want to match, a couple of examples of what you don't, and let a tool work backward to a pattern. The Regex Builder from Examples does exactly that — you supply positive examples (strings that should match) and negative ones (strings that should not), and it infers a pattern that fits all the positives and rejects every negative. It's faster and far less error-prone than building the regex from scratch, because the structure comes from your data instead of your guesswork. You still verify the edges yourself, but you're verifying a candidate instead of inventing one.

Why Real Strings Beat a Blank Editor

When you write a regex from memory, you're encoding your assumption about the data. The assumption is usually wrong in small ways. You think the order IDs are always six digits; three of them have a letter suffix. You think the dates use dashes; one batch uses slashes. The regex passes your mental test and fails on the third file.

Starting from examples flips the burden of proof. Instead of asking "what pattern do I think this data follows," you ask "what's the simplest pattern that covers these exact strings." The samples are ground truth. If you paste ten real lines and the tool finds a skeleton that fits all ten, you already know the pattern survives ten real cases — which is ten more than a hand-written guess gets before its first run.

This matters most on the formats you don't fully control: log lines from a service someone else wrote, exports from a vendor system, user-entered fields with their own quiet conventions. You don't need to reverse-engineer the spec. You collect specimens and let the structure surface.

Positive and Negative: Two Halves of One Definition

A pattern is defined as much by what it rejects as by what it accepts, and this is where giving only positives goes wrong. If you paste three SKUs and nothing else, the safest pattern that "fits" them is .+ — it matches all three, technically correct, completely useless.

Negative examples are how you pin down the boundary. They're the near-misses: the total line in the middle of your SKU export, the malformed date, the typo someone keeps making. Each negative eliminates a whole family of over-permissive candidates. Paste Total: 14 units as a negative alongside your product codes and every candidate that would accept arbitrary text gets thrown out automatically, because the tool checks each candidate against your negatives and discards any that match one.

You don't need many. Two or three well-chosen near-misses do more than twenty random unrelated strings. Pick the things that look almost right — those are the ones that catch a sloppy pattern.

Generalizing Without Going Too Broad or Too Narrow

Here's the real skill, and it's why a single "correct" answer doesn't exist. Take ["AB123", "CD456"]. Three reasonable patterns fit:

  • [A-Z]{2}\d{3} — tight: exactly two letters, exactly three digits
  • [A-Z]+\d+ — medium: some letters, then some digits
  • \S+ — loose: any run of non-whitespace

All three match both samples. The right choice depends entirely on what comes next. If you're validating input, you want the tight one — it rejects AB1234 and ABC12. If you're extracting from a noisy log where the code length varies, the tight version will silently skip the odd four-digit entry, and you want the medium one. The loose one is almost never what you want, but it's there to show you the ceiling.

This is why the builder returns several candidates ranked from tight to loose instead of one answer. Too narrow and you miss real data the day a five-digit code shows up as four. Too broad and you scoop up garbage. You pick the rung on the ladder that matches your tolerance, using the negative examples to push the floor up. The honest move is to lean tight, then widen one notch only when a real example forces you to.

Worked Example: A Pattern for Product Codes

Say a warehouse export hands you lines like these:

SKU-AX-00421-RED
SKU-AX-00422-BLU
SKU-BX-01193-BLK

And scattered through the same file:

Total: 14 units

Paste the three SKU lines as positives and Total: 14 units as a negative, then build. The tightest candidate comes back as:

SKU-[A-Z]{2}-\d{5}-[A-Z]{3}

Read it against the samples: literal SKU-, then a two-letter group (AX, BX), a dash, exactly five digits (00421), a dash, a three-letter color code (RED, BLU, BLK). It matches all three positives and rejects the total line cleanly. No counting digit positions by hand, no off-by-one on the color segment.

The same approach works for dates. Feed v1.2.3, v2.0.0, and v10.4.21 as positives, with version 1 and vNEXT as negatives, and the tight candidate v\d+\.\d+\.\d+ handles the variable-width major number (10 is two digits) while rejecting both near-misses. The negatives are doing real work here — without vNEXT in the list, a looser candidate that accepts letters after v would survive.

Always Verify the Edges Before You Ship

Inference is a heuristic, not a proof. The tool only ever sees the strings you paste. If your production data contains a shape that wasn't in your samples — a SKU with four digits instead of five, a date with a two-digit year, a color code that's two letters on one product line — the inferred regex will quietly miss it. That's not a flaw in the method; it's the nature of generalizing from a sample.

So treat the output as a strong first draft, then close the loop. Run the candidate against a larger real corpus, not just the handful you used to build it. Drop it into the Regex Tester and paste in a few hundred real lines to see what slips through or gets caught wrongly. Try one or two strings you didn't use during inference. When you find a miss, add it as a new positive (or negative) and rebuild — the pattern tightens or loosens to absorb the new case in seconds, which is the whole point.

A few habits keep this honest: paste at least three to five varied positives so the aligner can tell a fixed character from a variable field; always include negatives, even just two; and never mix unrelated shapes in one batch — an email and a phone number share no skeleton, so build one pattern per shape. Get those right and you'll spend your time deciding which rung of the tight-to-loose ladder you want, instead of debugging quantifiers in a blank editor.


Made by Toolora · Updated 2026-06-13