Khi một Character Class đi kèm quantifier (?, *, +, {m,n}), nó trở thành Repeating Character Class. Quantifier áp dụng cho toàn bộ lớp ký tự, không phải ký tự vừa khớp.
Ví dụ cơ bản
import re
# [0-9]+ khớp 1 hoặc nhiều chữ số (có thể khác nhau)
print(re.findall(r'[0-9]+', '579')) # ['579']
print(re.findall(r'[0-9]+', '333')) # ['333']
print(re.findall(r'[0-9]+', '922226')) # ['9', '2222', '6']
Khác biệt: Lặp class vs Lặp ký tự đã khớp (Backreference)
Nếu muốn lặp chính xác ký tự vừa khớp (ví dụ: '333' nhưng không khớp '579'), dùng Backreference:
# ([0-9])\1+ : Group 1 khớp 1 chữ số, \1+ lặp lại CHÍNH CHỮ SỐ ĐÓ
print(re.findall(r'([0-9])\1+', '333')) # ['3'] (khớp '333')
print(re.findall(r'([0-9])\1+', '579')) # [] (không khớp)
print(re.findall(r'([0-9])\1+', '922226')) # ['2'] (khớp '2222')
Quantifiers phổ biến
| Quantifier | Ý nghĩa |
|---|---|
? | 0 hoặc 1 lần |
* | 0 hoặc nhiều lần |
+ | 1 hoặc nhiều lần |
{m,n} | Từ m đến n lần |
Lookahead/Lookbehind để giới hạn ranh giới
Nếu ([0-9])\1+ khớp '2222' giữa '922226' mà bạn chỉ muốn khớp khi toàn bộ chuỗi là số lặp, dùng anchor hoặc lookaround:
# Chỉ khớp nếu CHUỖI TOÀN BỘ là số lặp lại
r'^(?:([0-9])\1+)$'
# Hoặc dùng lookaround cho ranh giới từ
r'(?
Tóm tắt
[abc]+= lặp class: khớp 'a', 'ab', 'abc', 'cba', 'aaa'...([abc])\1+= lặp ký tự đã capture: khớp 'aaa', 'bbb', 'ccc'... KHÔNG khớp 'ab', 'abc'.