Our app emits log lines in a format that evolved organically over four years and is documented in precisely zero places, which is to say it's documented the way most things are: in the heads of people who left. I needed a Python pattern to pull out the timestamp, level, request ID, and message body, and to skip the heartbeat lines that spam the file every two seconds and drown out anything useful. A year ago I did the older, dumber version of this and lost 40 minutes on regex101, nudging a quantifier back and forth like a raccoon batting at a shiny object, convinced the fix was one more `?` away.
The thing about hand-writing a non-trivial regex is that the feedback loop is brutal. You change one character, paste in a test string, see red, and you have no idea whether you broke the thing you were fixing or fixed the thing you were breaking. It's debugging with a blindfold on.
The faster version
This time I used the Build a Regex from Plain English with Tests and a Breakdown Table prompt. In must_match I wrote a plain-English description: 'a bracketed timestamp, then a level word like INFO or ERROR, then req= and an alphanumeric id, then the rest of the line is the message.' In must_not_match I put 'lines whose message contains HEARTBEAT or PING.' Engine: Python re. Gemini 2.5 Pro gave me back a single-line pattern with named capture groups — timestamp, level, request_id, message — a breakdown table explaining every token in the pattern, eight test cases with expected match/no-match and a reason for each, and a ready-to-paste snippet. Ninety seconds: read, copy, paste, done. The same task that cost me forty minutes the year before.
The assumption it caught before I shipped a bug
Right above the pattern it printed one quiet line: 'Assumption: timestamp is ISO 8601; confirm if it is epoch.' That stopped me cold, because ours is actually epoch milliseconds — a big ugly integer, not a date string. Had a less careful tool silently assumed ISO 8601 and produced a pattern that matched nothing on my real logs, I'd have spent an hour debugging a 'why is my parser returning zero rows' mystery, slowly losing my mind, never once suspecting the regex because it 'looked right.' The prompt's rule to surface exactly one assumption when the spec is ambiguous is the entire reason I trust the output enough to paste it instead of re-deriving it. A tool that tells you what it guessed is worth ten that guess silently.
Why the tables matter more than the pattern itself
Here's the dirty secret of regex: a pattern you can't read is a liability with a six-month fuse. You write it, it works, you forget how, and then it breaks and you're staring at `(?P<ts>\[[^\]]+\])` like it's a ransom note. The breakdown and test tables are the part that actually makes this maintainable, and structured tables are exactly where Gemini is strongest — it's exhaustive, it's organized, and it doesn't get bored on the eighth row.
- Two of the eight test cases covered edge cases I hadn't even thought to worry about: a log line with an empty message body, and a message containing embedded double quotes that could have broken my downstream JSON wrapping
- The generated snippet compiled the pattern once with `re.compile` outside the loop — a performance detail I would absolutely have forgotten and then paid for, because this parser runs over millions of lines in a hot path
- Six months from now, the breakdown table means I — or whoever inherits this — can read what the pattern does line by line without reverse-engineering it from the cryptic syntax
- It used named groups instead of numbered ones, so my downstream code reads `m['request_id']` instead of `m[3]`, which is the difference between maintainable and write-only code
There's a deeper reason I trust this workflow now: regex is a domain where 'looks right' and 'is right' diverge constantly, and the only honest way to close that gap is examples. By forcing the model to produce a test table drawn from both my match and no-match descriptions, the prompt makes it prove the pattern against the cases I actually care about, in front of me, before I commit. It's the difference between a pattern someone asserts works and a pattern I've watched pass eight tests.
I now reach for this any time a pattern would run longer than about thirty characters, which is my honest personal line for 'I will get this subtly wrong by hand and not notice for a week.' The test table is the deliverable I value most, because it's proof, not just a pattern. Grab the Build a Regex from Plain English with Tests and a Breakdown Table prompt on Prompt Dock and describe your messiest, most undocumented format in plain words — there's a good chance the single assumption it flags will save you more time than the pattern does.