Match.expand
The replacement half of re.sub, applied to a single Match: the same template syntax, the same errors, but it returns only the expanded template — not the rest of the string.
Common call
m.expand(r'\g<last>, \g<first>')
Returns
'Lovelace, Ada'
Replaces
f-strings built from m.group(1), m.group(2), …
Watch out
Template errors (bad escape, invalid group reference) raise re.PatternError
Match.expand(templatetemplate — Replacement template: \1…\99, \g<number>, \g<name>, plus escapes like \n and \t. Write it as a raw string.type: str · required)
→ str
Demo
Live evaluation
The first match of the pattern, expanded into the template.
Try:
Inputs
patternstra regular expression
textstrtext
templatestrtemplate
Code
import re m = re.search('(?P<first>\\w+) (?P<last>\\w+)', 'Ada Lovelace') m.expand('\\g<last>, \\g<first>')
Result
'Lovelace, Ada'
expand returns only the filled-in template; re.sub would also keep the text around the match. Escapes such as \n become real characters (the result shows '\n' because it is displayed with repr). Referring to a group the pattern does not have raises re.PatternError with a position inside the template.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| template | str | yes | Replacement template: \1…\99, \g<number>, \g<name>, plus escapes like \n and \t. Write it as a raw string. |
Return value
str — The template with group references replaced by the groups of this match.
Common patterns
One template, many records
finditer + expand formats every match.
import re lines = [m.expand(r'\g<name> <\g<email>>') for m in re.finditer(r'(?P<name>\w+): (?P<email>\S+)', text)]
Template from configuration
Templates can be stored as data, unlike f-strings.
import re label = m.expand(config['label_template'])
Examples
1. Named groups
import re
m = re.search(r'(?P<user>\w+)@(?P<host>[\w.]+)', 'mail ada@example.com now')
m.expand(r'\g<host> <- \1')
Returns
'example.com <- ada'2. Numbered groups
import re
re.match(r'(\w+) (\w+)', 'Ada Lovelace').expand(r'\2, \1')
Returns
'Lovelace, Ada'3. Only the template
import re
re.search(r'\d+', 'id 42 end').expand(r'<\g<0>>')
Returns
'<42>'4. Unmatched group → empty
import re
re.match(r'(a)(b)?', 'a').expand(r'[\1|\2]')
Returns
'[a|]'5. Bad reference
import re
re.match(r'(a)', 'a').expand(r'\2')
Returns
re.PatternError: invalid group reference 2 at position 1Pitfalls
1. Template without a raw string
In a normal string '\1' is the character with code 1 — the template never sees a group reference.
'\1'
import re re.match(r'(\w+)', 'hi').expand('<\1>')
'<\x01>'
r'\1'
import re re.match(r'(\w+)', 'hi').expand(r'<\1>')
'<hi>'
2. Escapes that are not allowed
Unknown escapes of ASCII letters are errors in templates, just like in re.sub.
r'\d'
import re re.match(r'(\d)', '7').expand(r'\d=\1')
re.PatternError: bad escape \d at position 0
plain text
import re re.match(r'(\d)', '7').expand(r'digit=\1')
'digit=7'
When to use
Use it
- Formatting a match with a stored or user-configurable template
- Reusing the exact re.sub template syntax for one match
Reach for something else
- Templates you write in code → an f-string with m["name"] is clearer
- Replacing inside the full text → re.sub
Notes
CPython impl
Match.expand calls re._compile_template (cached) and fills it — the same code path as re.sub with a string repl
Unmatched groups
Replaced with an empty string since Python 3.5
FAQ
It substitutes the groups of one match into a template, using the re.sub syntax: re.match(r'(\w+) (\w+)', 'Ada Lovelace').expand(r'\2, \1') gives 'Lovelace, Ada'.