RX

Advanced Techniques

Regular Expressions · 7 entries

Atomic Groups (Concept)

syntax
(?>pattern)   (PCRE/Java; not native in JS or Python re)
example
PCRE:  (?>\d+)\s matches '123 ' but NOT by backtracking into digits
Python (regex module):
  import regex
  regex.search(r'(?>\d+):', '123:')
output
Matches '123:' -- once the digits are consumed, the engine cannot give them back

Note Atomic groups discard all backtracking positions once the group matches. They are a performance optimization to prevent catastrophic backtracking. In Python, use the third-party 'regex' module. In JS, there is no direct equivalent -- simulate with a possessive quantifier mindset or restructure the pattern.

Conditional Patterns

syntax
(?(condition)yes-pattern|no-pattern)   (Python, PCRE)
example
Py (regex module):
  import regex
  # Match optionally quoted word -- closing quote only if opening exists
  regex.findall(r'(")?(\w+)(?(1)")', '"hello" world "test"')
output
Matches '"hello"' and '"test"' as quoted, 'world' as unquoted

Note Conditional patterns branch based on whether a group participated in the match. Python's built-in re supports (?(id)yes|no) syntax. Not available in JavaScript. Useful for matching balanced optional delimiters.

Recursive Patterns

syntax
(?R) or (?P>name)   (PCRE, Python regex module)
example
Python (regex module):
  import regex
  pattern = r'\((?:[^()]*|(?R))*\)'
  regex.findall(pattern, 'a(b(c)d)e(f)g')
output
["(b(c)d)", "(f)"]  (matches balanced/nested parentheses)

Note Recursive patterns can match nested structures like balanced parentheses or nested HTML. Not available in JavaScript or Python's built-in re -- requires the third-party regex module for Python or PCRE-based engines. Extremely powerful but can be hard to debug.

Unicode Property Escapes \p{...}

syntax
JS: /\p{Letter}/u    Python: regex.findall(r'\p{L}+', text)
example
JS:  'cafe\u0301 2024 Tokyo'.match(/\p{Letter}+/gu)
Py (regex module):
  import regex
  regex.findall(r'\p{N}+', 'Price: 42 or \u0664\u0662')
output
JS: ["cafe\u0301", "Tokyo"]
Py: ["42", "\u0664\u0662"]  (\p{N} matches any Unicode number)

Note Common categories: \p{L} (letter), \p{N} (number), \p{P} (punctuation), \p{S} (symbol), \p{Z} (separator), \p{Emoji}. In JS, requires the u flag. Python's built-in re does not support \p{} -- use the regex module. Essential for internationalized text processing.

Named Group References in Replacement

syntax
JS: $<name>    Python: \g<name>
example
JS:  'Smith, John'.replace(/(?<last>\w+), (?<first>\w+)/, '$<first> $<last>')
Py:  re.sub(r'(?P<last>\w+), (?P<first>\w+)', r'\g<first> \g<last>', 'Smith, John')
output
"John Smith"

Note Named group references in replacements improve readability over numeric \1, $1 references. JS uses $<name> in the replacement string while Python uses \g<name>. Works with both replace() and re.sub().

Non-Greedy Scanning Patterns

syntax
.*?target  (scan forward minimally until target is found)
example
JS:  'START data1 END noise START data2 END'.match(/START(.*?)END/g)
Py:  re.findall(r'START(.*?)END', 'START data1 END noise START data2 END')
output
JS: ["START data1 END", "START data2 END"]
Py: [" data1 ", " data2 "]  (findall returns groups)

Note The .*? idiom scans forward character by character until the following pattern matches. This is the standard approach for extracting content between delimiters. Be aware that .*? can still cause slowdowns on long strings with no match -- consider using negated character classes instead when possible.

Compiling Regex for Reuse

syntax
JS: const re = new RegExp(pattern, flags)
Python: re.compile(pattern, flags)
example
JS:  const dateRe = new RegExp('\\d{4}-\\d{2}-\\d{2}', 'g');
     dateRe.test('2026-04-04');
Py:  date_re = re.compile(r'\d{4}-\d{2}-\d{2}')
     date_re.findall('2026-04-04 and 2025-12-25')
output
JS: true
Py: ['2026-04-04', '2025-12-25']

Note Compiling is beneficial when the same pattern is used repeatedly (e.g., in a loop). Python caches the most recent patterns automatically, but explicit compilation is clearer and avoids cache eviction. In JS, the RegExp constructor requires double-escaping backslashes in string form.