Nearby lessons
131 of 159Python - Regex sub and subn
- Understand what substitution means in regular expressions
- Use re.sub() to replace matched patterns and return the modified string
- Understand how subn() returns a tuple with the replacement count
- Limit the number of replacements using the count parameter
- Compare sub() and subn() to choose the right function
Introduction to Substitution
Python's re module provides functions to replace matched Regular Expression patterns with another string.
The two important substitution functions are:
sub()
subn()
Both functions perform replacement, but their return values are different.
sub()
│
└── Returns the modified string
subn()
│
└── Returns a tuple
(modified string, number of replacements)
Simple Definition:
Substitution means replacing the text matched by a Regular Expression with another text.
Suppose we have the following string:
a7b9c5kz
We want to replace every digit with:
#
The Regular Expression:
[0-9]
matches:
7
9
5
After replacement:
a#b#c#kz
This process is called substitution.
1. The sub() Function
The sub() function replaces every occurrence of the given Regular Expression pattern with the specified replacement string.
Simple Definition:
sub() replaces matched occurrences with another string and returns the resulting string.
Syntax:
re.sub(regex, replacement, target_string)
We can also write:
re.sub(pattern, repl, string)
Understanding sub() Syntax
re.sub(regex, replacement, target_string)
│ │ │
│ │ └── String to search
│ │
│ └── New replacement value
│
└── Regular Expression pattern
Example:
re.sub("[0-9]", "#", "a7b9c5kz")
Here:
| Argument | Value | Purpose |
|---|---|---|
| Regex | [0-9] |
Find digits |
| Replacement | # |
Replace every matched digit with # |
| Target | a7b9c5kz |
String in which replacement is performed |
sub() Demo Program
Consider the statement:
s = re.sub("[0-9]", "#", "a7b9c5kz")
The target string is:
a7b9c5kz
The pattern:
[0-9]
matches every digit.
Python searches the target from left to right.
a → No Match → Keep a
7 → Match → Replace with #
b → No Match → Keep b
9 → Match → Replace with #
c → No Match → Keep c
5 → Match → Replace with #
k → No Match → Keep k
z → No Match → Keep z
Therefore:
Original : a7b9c5kz
Result : a#b#c#kz
Replacement Diagram:
Original String
a 7 b 9 c 5 k z
│ │ │
▼ ▼ ▼
# # #
Result
a # b # c # k z
Only the characters matched by the Regular Expression are replaced.
All non-matching characters remain unchanged.
sub() with \d
For this basic ASCII example:
[0-9]
and:
\d
both match the digits:
7
9
5
Therefore, both examples produce:
a#b#c#kz
Note: In Python 3, \d is Unicode-aware by default, so its behaviour is broader than [0-9] for some Unicode text.
sub() with Alphabet Replacement
The pattern:
[a-z]
matches every lowercase alphabet character.
The target:
a7b9c5kz
contains the lowercase letters:
a
b
c
k
z
Each one is replaced with #.
a → #
7 → 7
b → #
9 → 9
c → #
5 → 5
k → #
z → #
Therefore:
#7#9#5##
sub() When Pattern is Not Found
The target string:
abcdefgh
does not contain any digit.
Therefore:
[0-9]
does not match anything.
No replacement takes place, so the original content remains unchanged:
abcdefgh
sub() Execution Flow
Program Starts
│
▼
import re
│
▼
Pattern = [0-9]
│
▼
Replacement = "#"
│
▼
Target =
"a7b9c5kz"
│
▼
re.sub()
│
▼
Search Target
from Left to Right
│
▼
Pattern Matches?
│
┌──┴──────────┐
│ │
Yes No
│ │
▼ ▼
Replace with Keep Original
"#" Character
│ │
└──────┬──────┘
▼
Continue Search
│
▼
End of String
│
▼
Return Modified String
│
▼
"a#b#c#kz"
│
▼
Print
│
▼
End
2. The subn() Function
The subn() function performs substitution just like sub().
But there is one important difference.
subn() also tells us how many replacements were performed.
Simple Definition:
subn() replaces matched occurrences and returns a tuple containing the modified string and the number of replacements.
Syntax:
re.subn(regex, replacement, target_string)
Return Value of subn()
The subn() function returns a tuple.
The general form is:
(modified_string, number_of_replacements)
For example:
('a#b#c#kz', 3)
Here:
'a#b#c#kz'
│
└── Modified String
3
│
└── Number of Replacements
A tuple returned by subn() contains exactly two items:
| Position | Value | Meaning |
|---|---|---|
0 |
Modified string | Result after substitution |
1 |
Replacement count | Number of substitutions performed |
Example:
t = ('a#b#c#kz', 3)
t[0] → 'a#b#c#kz'
t[1] → 3
subn() Demo Program
The important statement is:
t = re.subn("[0-9]", "#", "a7b9c5kz")
The pattern:
[0-9]
finds:
7
9
5
Each digit is replaced with:
#
The resulting string becomes:
a#b#c#kz
The total number of replacements is:
3
Therefore, subn() returns:
('a#b#c#kz', 3)
Accessing Values from the subn() Tuple
The returned tuple is:
('a#b#c#kz', 3)
The first element is available at index 0:
t[0]
which gives:
a#b#c#kz
The second element is available at index 1:
t[1]
which gives:
3
Because subn() returns two values inside a tuple, we can also unpack them directly:
result, count = re.subn("[0-9]", "#", "a7b9c5kz")
print("Result:", result)
print("Number of Replacements:", count)
Output:
Result: a#b#c#kz
Number of Replacements: 3
Conceptually:
('a#b#c#kz', 3)
│ │
▼ ▼
result count
Therefore:
result = "a#b#c#kz"
count = 3
subn() When No Match Exists
The target:
abcdefgh
does not contain any digit.
Therefore, no substitution is performed.
The resulting string remains:
abcdefgh
The replacement count is:
0
Hence:
('abcdefgh', 0)
subn() Execution Flow
Program Starts
│
▼
import re
│
▼
Pattern = [0-9]
│
▼
Replacement = "#"
│
▼
Target =
"a7b9c5kz"
│
▼
re.subn()
│
▼
Set Replacement
Count = 0
│
▼
Search Target
from Left to Right
│
▼
Pattern Matches?
│
┌──┴─────────────┐
│ │
Yes No
│ │
▼ ▼
Replace with # Keep Original
│ │
▼ │
Increase Count │
│ │
└────────┬───────┘
▼
Continue
│
▼
End of String
│
▼
Create Tuple
(modified string, count)
│
▼
('a#b#c#kz', 3)
│
▼
Return
│
▼
End
sub() vs subn()
Both functions perform the same basic substitution operation.
The main difference is their return value.
Pattern Match
│
▼
Replace
│
┌────────┴────────┐
│ │
▼ ▼
sub() subn()
│ │
▼ ▼
Modified String Modified String
+
Replacement Count
│ │
▼ ▼
"a#b#c#kz" ("a#b#c#kz", 3)
| Feature | sub() | subn() |
|---|---|---|
| Performs substitution | Yes | Yes |
| Uses Regular Expression | Yes | Yes |
| Replaces matching occurrences | Yes | Yes |
| Returns modified string | Yes | Inside tuple |
| Returns replacement count | No | Yes |
| Return type in these examples | String | Tuple |
| No matches | Original string | (original_string, 0) |
Both functions use:
Pattern = [0-9]
Replacement = #
Target = a7b9c5kz
Both replace:
7 → #
9 → #
5 → #
So both produce the same modified text:
a#b#c#kz
But their returned values differ.
sub() → a#b#c#kz
subn() → ('a#b#c#kz', 3)
The additional 3 tells us that three replacements were performed.
Complete Execution Flow:
Start
│
▼
import re
│
▼
Define Pattern
│
▼
Define Replacement
│
▼
Target String
│
┌───────────┴───────────┐
│ │
▼ ▼
sub() subn()
│ │
▼ ▼
Find Matching Find Matching
Occurrences Occurrences
│ │
▼ ▼
Replace Matches Replace Matches
│ │
▼ ▼
Modified String Count Replacements
│ │
│ ▼
│ Create Tuple
│ │
▼ ▼
Return String Return (String, Count)
│ │
└───────────┬───────────┘
▼
Output
│
▼
End
Limiting Replacements with count
Both sub() and subn() support an optional count argument.
Syntax:
re.sub(pattern, replacement, string, count)
re.subn(pattern, replacement, string, count)
The count value specifies the maximum number of replacements.
For example:
re.sub("[0-9]", "#", "a7b9c5", 2)
Only the first two digits are replaced.
In the program below, the target contains three digits:
7
9
5
But:
count = 2
Therefore, only the first two matches are replaced:
7 → #
9 → #
5 → remains unchanged
The result is:
a#b#c5kz
Default count behaviour: If the count argument is not specified, Python replaces all non-overlapping matches. For example:
re.sub("[0-9]", "#", "a7b9c5")
replaces all three digits.
We can also explicitly use count = 0 to mean no replacement limit:
re.sub("[0-9]", "#", "a7b9c5", 0)
Result:
a#b#c#
subn() with count
Only two substitutions are allowed.
Therefore:
Modified String = a#b#c5kz
Replacement Count = 2
The returned tuple is:
('a#b#c5kz', 2)
Quick Revision and Important Notes
Quick Revision:
sub()
│
├── Finds matches
│
├── Replaces matches
│
└── Returns modified string
subn()
│
├── Finds matches
│
├── Replaces matches
│
├── Counts replacements
│
└── Returns tuple
│
└── (modified_string, count)
Easy memory rule:
sub → Substitute
subn → Substitute + Number
Summary:
- Substitution means replacing text matched by a Regular Expression.
- Python provides
sub()andsubn()for Regular Expression substitution. sub()replaces matched occurrences with the specified replacement.sub()returns the modified string.- The basic syntax is
re.sub(pattern, replacement, target). subn()performs the same substitution operation.subn()additionally counts how many substitutions were performed.subn()returns a tuple.- The tuple format is
(modified_string, number_of_replacements). - For
a7b9c5kz, replacing digits with#producesa#b#c#kz. - In that example,
subn()returns('a#b#c#kz', 3). - If no match exists,
sub()returns the unchanged string. - If no match exists,
subn()returns the unchanged string together with count0. - Both functions support an optional
countargument to limit the number of substitutions.
Important Notes:
sub()andsubn()are substitution functions of Python'sremodule.- The first argument is the Regular Expression pattern.
- The second argument specifies the replacement.
- The third argument is the target string.
sub()returns the resulting string after substitution.subn()returns a tuple rather than only the resulting string.- The first item of the
subn()tuple is the modified string. - The second item is the number of replacements actually performed.
subn()can be remembered as substitution + number.- Only text matched by the Regular Expression is replaced.
- Non-matching text remains unchanged.
- If no matches exist, the target content remains unchanged.
- A no-match result from
subn()has replacement count0. - The returned tuple from
subn()can be accessed using indexes0and1. - The tuple can also be unpacked directly into two variables.
- The optional
countargument can limit how many matches are replaced. - If
countis omitted or is0, all non-overlapping matches are replaced. - Do not confuse
subn()'s replacement count with the number of characters in the resulting string.
- Substitution replaces the text matched by a Regular Expression with another text
- re.sub() replaces every matching occurrence and returns the modified string
- re.subn() returns a tuple containing the modified string and the number of replacements
- The optional count parameter specifies the maximum number of replacements
- If no match exists, sub() returns the original string and subn() returns (original_string, 0)