问题: 正则表达式中*、+、?的基础含义分别是什么?

👇 点击展开/折叠 面试背诵模板(建议先背这个) `*`、`+`、`?` 都是正则中的量词(限定符),用于修饰其前面的原子字符或分组,控制该元素出现的次数。`*` 表示匹配前一个字符零次或多次,等价于 `{0,}`;`+` 表示匹配前一个字符一次或多次,等价于 `{1,}`;`?` 表示匹配前一个字符零次或一次,等价于 `{0,1}`。三者默认均为贪婪匹配模式,即尽可能多地向后匹配字符。
---

三者的量化对比

量词 语义 等价写法 记忆口诀
* 零次或多次 {0,} “可有可无,多多益善”
+ 一次或多次 {1,} “至少一次,上不封顶”
? 零次或一次 {0,1} “要么没有,要么一次”
1
2
3
4
5
6
import re
print(re.fullmatch(r'a*', '')) # ✅ 空串匹配(零次)
print(re.fullmatch(r'a*', 'aa')) # ✅ 匹配
print(re.fullmatch(r'a+', '')) # ❌ None(至少一次)
print(re.fullmatch(r'a?', '')) # ✅ 空串匹配(零次)
print(re.fullmatch(r'a?', 'a')) # ✅ 匹配

贪婪匹配的实际影响(常见认知盲区)

默认情况下,这些量词会尽可能多地匹配字符(贪婪)。例如使用 .+ 匹配 "a"b" 时,会匹配整个字符串 "a"b",而非预期中的 "a"。若需最小匹配(懒惰模式),需在量词后追加 ?,即 .+? 或 *?。

1
2
3
text = "<div>hello</div><span>world</span>"
print(re.findall(r'<.*>', text)) # ['<div>hello</div><span>world</span>'](贪婪)
print(re.findall(r'<.*?>', text)) # ['<div>', '</div>', '<span>', '</span>'](懒惰)

零次匹配的空值陷阱(面试高频)

由于 * 和 ? 支持零次匹配,当使用 re.match() 或 re.search() 时,即使目标字符串中不存在该字符,匹配也可能成功(返回空字符串对象),从而绕过逻辑校验。例如用 r'\d*' 校验非空数字时,空字符串也会通过,实际开发中应优先使用 + 保证至少一位。

1
2
print(re.match(r'\d*', 'abc'))   # ✅ 匹配成功(返回空字符串),不会返回 None
print(re.match(r'\d+', 'abc')) # ❌ None,校验更严格