Module re của Python hỗ trợ các phép toán tập hợp (set operations) bên trong Character Class: Intersection (giao), Subtraction (hiệu), Union (hợp). Cú pháp sử dụng &&, --, ||.
1. Intersection (Giao) - Toán tử &&
Khớp ký tự thuộc CẢ HAI lớp con.
import re
# Ký tự KHÔNG phải whitespace (\S) VÀ KHÔNG phải digit (\D)
# => Chữ cái và ký tự đặc biệt (không số, không space)
pattern = r'[\S&&\D]'
print(re.findall(pattern, "a1 !B")) # ['a', '!', 'B']
2. Subtraction (Hiệu) - Toán tử --
Khớp ký tự thuộc lớp thứ nhất NHƯNG KHÔNG thuộc lớp thứ hai.
# Chữ cái thường [a-z] TRỪ nguyên âm [aeiou] = phụ âm
pattern = r'[a-z--[aeiou]]'
# Hoặc viết gọn (khi lớp trừ không có range):
pattern = r'[a-z--aeiou]'
print(re.findall(pattern, "hello world")) # ['h', 'l', 'l', 'w', 'r', 'l', 'd']
3. Union (Hợp) - Toán tử ||
Khớp ký tự thuộc ÍT NHẤT MỘT trong các lớp.
# Ký tự '0' HOẶC ký tự word không phải digit (\w nhưng không \d)
# \w = [a-zA-Z0-9_], \D = non-digit => [\w&&\D] = [a-zA-Z_]
# Union: 0 hoặc [a-zA-Z_]
pattern = r'[0||[\w&&\D]]'
print(re.findall(pattern, "0 a _ 5")) # ['0', 'a', '_']
Cú pháp tổng quát
[base_class && [sub_class]] # Intersection
[base_class -- [sub_class]] # Subtraction
[class1 || class2 || class3] # Union
Lưu ý
- Cú pháp này là mở rộng của Python regex, không phải chuẩn POSIX/PCRE.
- Lớp trừ (
--) phải là phần tử cuối cùng trong class. - Có thể lồng nhau:
[0-9--[0-7--[0-3]]]=[0-9--[4-7]]=[0-38-9]. - Không thể trừ tuần tự:
[a-z--[aeiou]--[bcdf]]SAI. Hãy gộp:[a-z--[aeioubcdf]].