Python regex cho phép lồng phép trừ (Subtraction) bên trong Character Class: [outer_class -- [inner_class -- [nested_class]]].
Cơ chế hoạt động
Đánh giá từ trong ra ngoài:
- Tính
inner_class -- nested_class→ kết quả trung gian. - Tính
outer_class -- (kết quả trung gian).
Ví dụ minh họa
import re
# [0-9 -- [0-7 -- [0-3]]]
# B1: [0-7] -- [0-3] = [4-7]
# B2: [0-9] -- [4-7] = [0-3] + [8-9] = [0-38-9]
pattern = r'[0-9--[0-7--[0-3]]]'
print(re.findall(pattern, '0123894567')) # ['0', '1', '2', '3', '8', '9']
Quy tắc quan trọng
- Phép trừ
-- [...]phải là phần tử cuối cùng trong character class. - SAI:
[0-9--[4-7]a-d](có 'a-d' sau phép trừ). - ĐÚNG:
[0-9a-d--[4-7]](gộp base class trước, trừ sau). - Phép trừ áp dụng cho toàn bộ base class (kể cả các phần tử trước nó).
Ứng dụng thực tế: Trừ nhiều script Unicode
Muốn trừ cả Basic Latin (ASCII) và Arabic khỏi tất cả chữ Unicode (\p{L}):
# Gộp 2 script cần trừ thành 1 class, rồi trừ 1 lần
[\p{L}--[\p{IsBasicLatin}\p{IsArabic}]]
Lưu ý: \p{...} cần regex engine hỗ trợ Unicode properties (Python re không hỗ trợ, dùng module regex bên thứ 3).
Tóm tắt
- Hỗ trợ lồng trừ:
[A--[B--[C]]]. - Phép trừ luôn ở cuối class.
- Không trừ tuần tự được, hãy gộp lớp trừ.
- Python stdlib
rehỗ trợ--,&&,||nhưng không hỗ trợ \p{...}.