Drop-in for Python re#
Full drop-in, strict by default — import real as re and use the API you
already know; every accepted pattern is guaranteed linear. An unsupported
construct raises real.error instead of silently backtracking.
Adopt / swap#
import real as re # drop-in for the standard library's re
m = re.search(r"(\w+)@(\w+)", "info@example.com")
m.group(2) # 'example' — linear time, no backtracking cliff
API offered#
The re surface you already call is offered whole — the module functions,
Pattern’s methods, Match’s accessors — same names, same shapes.
Flags re.I, re.M, re.S, re.X, re.A behave the same; Unicode
\w \d \s \b and IGNORECASE folding follow re in text mode.
Beyond re — flagged extensions, never silent divergences:
Pattern.count_matches(text)— count matches without buildingMatchobjects.real.compile(pat, fallback=True)(or module-widereal.fallback = True) — delegate a rejected pattern to stdlibrefor that pattern, trading its linear-time guarantee;Pattern.enginesays which backend ran.\p{…}property classes and the\N{U+XXXX}scalar escape — supersets that stdlibrerejects (why).
Object-level reference: Python API.
Differences & limitations#
Every intentional divergence from re — semantics, rationale, pins — lives in
Differences from Python re. The one
binding-specific line: \N{NAME} is resolved by Python’s unicodedata, so
character-name lookup exists only on the Python surface (no C++ name table).
Comparison#
Python re is a backtracker. REAL is linear on every accepted pattern. The
shared binding bench — same harness, match counts checked before timing — lives
in the
performance ledger;
the reading is Performance.