类是什么
字符类用方括号括起一组候选字符,整体只匹配其中任意一个字符,不是匹配整组字符。它是一对多关系的写法:方括号里写多少种,外面就多一个可选项,但消耗的字符数始终是一。
匹配顺序无关
类内候选是集合而不是序列,先写谁后写谁不影响结果。需要按顺序匹配多个字符时,要用多个类或字面量串起来,例如邮政编码这类固定结构的字段应拆成若干个类依次书写。
基本信息
| 基本语义 | 匹配类中任意一个字符,恰好消耗一个字符 |
|---|---|
| 区间写法 | 用连字符连接两端,如 a 到 z、0 到 9,两端包含在内 |
| 取反写法 | 左括号后紧跟脱字符表示「不属于这些字符」 |
| 右括号 | 想匹配右括号本身,要把它放在类的首位,或加反斜杠 |
| 类内退化 | 点号、星号、加号、问号、圆括号、竖线在类内都是普通字符 |
| 区间顺序 | 区间的起止必须按字符编码递增,反过来写多数引擎会报错 |
典型使用场景
- 校验账号、单号这类只允许固定字符集的字段,比用点号更严格
- 匹配十六进制、Base64、URL 安全字符等已知字母表
- 提取配置文件里的键名字符集,避免把注释符号或空格吞进来
- 把一批同义分隔符(逗号、分号、竖线)统一当作分隔符处理
- 配合取反写法排除引号,用于简易的带引号字符串提取
写法与边界
写法与边界
import re
re.findall(r'[abc]', 'a1b2c') # 命中类中任意一个字符
re.findall(r'[a-f0-9]', 'xA9fz') # 区间可以拼接多个段
re.findall(r'[^0-9]', 'a1b2') # 取反:非数字字符
re.search(r'[]]', 'x]') # 右括号放首位才表示它自己
re.search(r'[-a]', '-') # 连字符放首位或末位即字面量
re.findall(r'[.]', 'a.b') # 类内点号是普通字符,不是通配类内符号行为
| 写法 | 含义 | 注意点 |
|---|---|---|
| 连字符在中间 | 表示区间 | 想表示本身要放首位、末位或转义 |
| 脱字符在首位 | 整个类取反 | 放其他位置就是普通字符 |
| 右括号 | 需放首位才算字面量 | 否则会提前结束类 |
| 反斜杠 | 仍保持转义语义 | 类内写空白类或数字类同样有效 |
| 点号与量词符号 | 退化为普通字符 | 不必额外转义,写了也不报错 |
写好一个类之后先自问两件事:它到底能匹配几个字符,区间端点是否包含。绝大多数「匹配结果少了一位」的问题,都是把类当成字符串而不是当成单字符集合导致的。
多数引擎允许在类内使用简写字符类,例如数字类、单词字符类、空白类,可与其他字符混排。混排之后区间与简写之间的边界要画清楚,否则容易写出看似合理实则宽松的集合。