C.W.K.
Stream
Lesson 02 of 12 · published

Possessive Quantifiers Revisited

~6 min · possessive, quantifier

Level 0Pattern-Curious
0 XP0/90 lessons0/15 achievements
0/100 XP to next level100 XP to go0% complete

Possessive vs atomic — the same idea

Possessive quantifiers (*+, ++, ?+, {n,m}+) and atomic groups achieve the same thing — disable backtracking — through different syntax.

a++ is equivalent to (?>a+). Both refuse to give back characters once consumed.

When to use which

Possessive: when you're applying the no-backtrack rule to a single quantifier. \d++, \w*+.

Atomic group: when you're wrapping a multi-element pattern and want to lock the whole thing. (?>\d{3}-\d{4}) wouldn't backtrack into a different split of dashes and digits.

Engine support comparison

EngineAtomicPossessive
Python re 3.11+
Python regex
PCRE / PHP
Java
Ruby✓ (1.9+)
.NET
JavaScript
RE2/Go

The portable workaround

If your engine has neither (notably JavaScript), the workaround is to refactor the pattern to not need backtracking. Use negated character classes ([^X]+ instead of .+?X) or anchored alternation. Often makes the pattern faster AND more readable.

Code

Possessive equivalents·python
import sys
import re

if sys.version_info >= (3, 11):
    # Possessive
    re.search(r'\d++X', 'aaa')   # fails fast — \d won't match anyway

    # Atomic equivalent
    re.search(r'(?>\d+)X', 'aaa')

    # Both protect against backtracking explosion
    # re.search(r'\d+X', '9'*30 + 'Y')  # slower due to backtracking
    # re.search(r'\d++X', '9'*30 + 'Y')  # immediate fail

# Portable workaround: negated character class instead of .+?
# Bad (greedy with backtrack)
re.search(r'".*?"', '"hello" world')

# Better (no backtrack possible)
re.search(r'"[^"]*"', '"hello" world')

# This works in EVERY engine, including JavaScript and RE2

External links

Exercise

Take a pattern with .+? and rewrite it with [^X]* where X is the natural delimiter. Time both on a long string. The negated-class version should be at least as fast, often faster, and portable to engines without atomic groups.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.