Regular Expressions — Learning Library¶
One regular-expression question per page, put to several engines at once — and every answer backed by a program that runs, whose output is pasted in by a tool and checked in CI.
Regular expressions are the rare topic where everyone knows the syntax and almost nobody knows the semantics. \1, (?=…) and (?<=…) are in every cheat sheet; what they mean differs between Python and JavaScript in ways that change whether your pattern is correct. This library is organised around those differences.
The languages in front are Rust, Python and ABAP, with Perl, JavaScript, Ruby, Java, Go, grep and sed brought in wherever they answer differently — which is most of the time.
Chapters¶
| Start here | The one rule, the four engine lineages, and where to go first. |
| Keywords | One page per construct, thirty-three of them, each with a table made by handing the same rows to eight engines. |
| Topics | One page per job — validating, extracting, splitting, escaping, porting, securing — pulling the keywords and chapters together. |
| Backreferences | \1 matches text, not a pattern. Four lessons: what it is, forward references, the $1 that is not a backreference at all, and what the feature costs. |
| Lookaround | Zero-width assertions, the two traps everyone hits, and how wide a lookbehind may be in seven engines. |
| Backtracking | The patterns everybody writes that never answer, and the (?>…) / a++ that fix them by changing what they match. |
| Unicode | What \w and \b mean once the subject is not ASCII, \p{…} and its misspellings, and the folding table behind (?i). |
| Anchors and flags | $ is not the end of the string, and m means two different things depending on which engine you ask. |
| Match semantics | Leftmost-first against leftmost-longest, greedy against lazy: one pattern, two engines, different answers, no error. |
| Recursion and conditionals | (?R), \g<0>, (?(1)…) and (?(DEFINE)…) — including the engines that accept the syntax while meaning something else. |
| Engines | Eleven constructs × five engines, measured by compiling each pattern. Where ABAP sits, and what to write in Rust and Go, which have no lookaround at all. |
| Resources | Official documentation per engine, books worth owning, and the sibling libraries. |
A taste of it¶
The same pattern, handed to two engines, meaning two different things — from forward references:
^(?:\1x|(a))+$ against "ax"
Perl, PCRE2, Ruby, Java, Rust (fancy-regex) no match
JavaScript match
Python does not compile
JavaScript is not more capable there. It treats a backreference to an unset group as matching the empty string, and it clears capture groups on every iteration of a quantifier — two rules that quietly turn the pattern into something else. Nothing warns you.
How it is checked¶
python3 tools/run_examples.py # run every example, refill every page's output block
python3 tools/check_all.py # every gate CI runs, in CI's order
uv run --group docs mkdocs serve # preview the site
139 examples in Python, Perl, JavaScript, Ruby, Java, C, Go, Rust, bash, grep and sed run on every push, on Ubuntu — which is a second machine, not the one they were written on, and so a second opinion about every answer key. The fourteen ABAP examples are source-only and say so; abaplint parses them instead — see CONTRIBUTING.md.