FormulaProof · Evidence
Execution log
What Google Sheets regex actually supports, and what it silently does instead
| Cell | Formula | What Google returned |
|---|---|---|
| B1 | =REGEXMATCH("abc123","\d+") baseline: REGEXMATCH finds digits Sanity check. If this fails, the harness itself is broken. | TRUE |
| B2 | =REGEXEXTRACT("Order 4821 shipped","\d+") baseline: REGEXEXTRACT pulls the first match | 4821 |
| B3 | =REGEXREPLACE("John Smith","(\w+) (\w+)","$2 $1") baseline: REGEXREPLACE swaps groups with $1 / $2 Dollar-sign backreferences are the Sheets replacement syntax. | Smith John |
| B4 | =REGEXMATCH("abc123","abc(?=123)") RE2 limit: positive lookahead (?=...) Works on regex101. Here it is not #ERROR! — it is #REF!, the error people associate with a deleted cell reference. That is why they hunt for a typo that does not exist. | #REF! |
| B5 | =REGEXMATCH("abc","a(?!b)") RE2 limit: negative lookahead (?!...) | #REF! |
| B6 | =REGEXMATCH("abc123","(?<=abc)123") RE2 limit: lookbehind (?<=...) | #REF! |
| B7 | =REGEXMATCH("abab","(ab)\1") RE2 limit: backreference inside the pattern Backreferences exist in the REPLACEMENT string of REGEXREPLACE, but never in the pattern. | #REF! |
| B8 | =REGEXMATCH("héllo","\p{L}+") Sheets limit: Unicode character class \p{L} RE2 supports this. Google Sheets is the exception Google names in its own docs. This one catches people who already know RE2. | #REF! |
| B9 | =REGEXMATCH("abc","(abc") unbalanced parenthesis is also #REF!, not #ERROR! A malformed regex and an unsupported one produce the same error. The cell tells you nothing about which. | #REF! |
| B10 | =ERROR.TYPE(REGEXMATCH("abc123","abc(?=123)")) cross-check: ERROR.TYPE of an unsupported pattern Independent confirmation of the error type. ERROR.TYPE returns 4 for #REF!, 3 for #VALUE!, 7 for #N/A, 8 for #ERROR!. We do not take one measurement's word for it. | 4 |
| B11 | =ERROR.TYPE(REGEXEXTRACT("abc","\d")) cross-check: ERROR.TYPE of REGEXEXTRACT with no match | 7 |
| B12 | =IFERROR(REGEXMATCH("abc123","abc(?=123)"),"caught") an unsupported pattern is catchable with IFERROR If IFERROR swallows it, a broken pattern can hide inside a working-looking spreadsheet forever. | caught |
| B13 | =REGEXEXTRACT("abc","\d") REGEXEXTRACT with no match A different error from an invalid pattern. People wrap both in IFERROR without noticing. | #N/A |
| B14 | =REGEXMATCH("cat dog","\bdog\b") supported: word boundary \b | TRUE |
| B15 | =REGEXEXTRACT("<a><b>","<(.+?)>") supported: lazy quantifier +? | a |
| B16 | =REGEXMATCH("ABC","(?i)abc") supported: inline case-insensitive flag (?i) | TRUE |
| B17 | =REGEXEXTRACT("x=1","(?P<digit>\d)") supported: RE2 named capture group (?P<name>...) RE2's own spelling. | 1 |
| B18 | =REGEXEXTRACT("x=1","(?<digit>\d)") supported: JavaScript named group syntax (?<name>...) also works Measured, not assumed. Sheets accepts both spellings, and ignores the name either way — REGEXEXTRACT returns groups in order. | 1 |
| B19 | =REGEXREPLACE("John Smith","(\w+) (\w+)","\2 \1") trap: backslash backreference in the replacement string No error. The backslashes vanish and you are left with the literal digits. Worse than an error, because an error tells you to stop. | 2 1 |
| B20 | =REGEXREPLACE("abc","b","[$0]") trap: $0 is the whole match in the replacement string | a[b]c |
| B21 | =REGEXREPLACE("abc","b","[$1]") trap: $1 when the pattern has no capture group It is an error, not a silent empty string. We did not know, so we measured. | #N/A |
Every row above was written into a real Google Sheet and read back through the Sheets API on 2026-07-09. The case file and this log are in the repository, and the build refuses to run if they disagree.
Why this page exists
Anyone can write that lookahead does not work in Google Sheets. It is in Google's documentation, one link away, and a language model will tell you the same thing in a second.
What almost nobody does is run it. So this page is the run. Each formula above was written into a cell through the Sheets API, and the value in the third column is what came back — not what we expected, not what the documentation says, not what a model predicted.
Some rows are marked observed. Those are cases where we did not know the answer beforehand, so we measured instead of asserting. Guessing and then presenting the guess as a finding is exactly the failure mode this site was built to avoid.
If any formula here changes what it does, the log goes stale and the site refuses to build. Tell us if you find one that is wrong before we do.