正则表达式
常用组合
正则表达式中,常用组合是基于元字符、量词和模式修饰符的灵活搭配,用于解决特定匹配场景。以下是开发中高频使用的经典组合,按功能分类整理,附场景说明和示例:
一、基础匹配组合
- 任意字符匹配
.*(贪婪匹配)- 含义:匹配任意字符(除换行符)0 次或多次,尽可能多匹配。
- 示例:文本
a-b-c,用a.*c匹配a-b-c(从a到最后一个c)。
.*?(非贪婪匹配)- 含义:匹配任意字符(除换行符)0 次或多次,尽可能少匹配(遇到满足后续条件则停止)。
- 示例:文本
a-b-c,用a.*?c匹配a-b-c(若文本是a-b-c-d-c,则匹配a-b-c)。
- 数字与非数字
\d+:匹配1 个或多个数字(等价于[0-9]+)。- 用途:提取手机号、身份证号等数字串,如
13800138000。
- 用途:提取手机号、身份证号等数字串,如
\D+:匹配1 个或多个非数字(等价于[^0-9]+)。- 用途:提取数字外的字符,如从
age:25中匹配age:。
- 用途:提取数字外的字符,如从
- 空白字符
\s+:匹配1 个或多个空白字符(空格、Tab、换行符\n等)。- 用途:处理多余空格,如
a b中匹配两个空格。
- 用途:处理多余空格,如
\S+:匹配1 个或多个非空白字符。- 用途:提取连续非空白内容,如从
name: Alice中匹配Alice。
- 用途:提取连续非空白内容,如从
非贪婪匹配
各部分含义
.:匹配任意单个字符(默认不包括换行符\n,除非开启单行模式re.DOTALL或s标志)。*:量词,表示匹配前面的元素(这里是.****)0 次或多次(贪婪模式,即尽可能多匹配)。?:跟在*后,表示非贪婪模式(也叫懒惰模式),即尽可能少地匹配,一旦满足后续条件就停止。
作用:非贪婪匹配任意字符序列
.*? 的核心功能是:匹配从当前位置开始,到第一个满足「后续正则条件」的位置为止的所有字符(不包括换行符,除非特殊设置)。
示例对比(贪婪 vs 非贪婪)
假设文本为:"aXXbXXc",用不同正则匹配:
- 贪婪模式
a.*b:会匹配aXXb(尽可能多匹配,直到最后一个b)。 - 非贪婪模式
a.*?b:只会匹配aXXb中的aXXb?不,这里更明显的例子是文本a1b2b3:a.*b会匹配a1b2b(贪婪到最后一个b)。a.*?b会匹配a1b(非贪婪,遇到第一个b就停止)。
常见使用场景
(1)提取两个标记之间的内容
例如,提取 HTML 标签 <div> 和 </div> 之间的内容(非贪婪避免跨多个标签匹配):<div>.*?</div>
- 文本:
<div>1</div><div>2</div> - 匹配结果:
<div>1</div>(只匹配第一个标签对,而非整个字符串)。
(2)处理 Markdown 代码块(如前面的例子)
匹配 开头和 结尾之间的内容,避免跨多个代码块:.*?
- 非贪婪模式确保只匹配单个代码块,而不是从第一个
到最后一个的所有内容。
(3)忽略换行符的限制(需开启单行模式)
默认 . 不匹配换行符 \n,若要让 .*? 匹配包括换行符在内的所有字符,需开启单行模式(Python 中用 re.DOTALL,JavaScript 中用 s 标志):
- 正则:
(?s)start.*?end((?s)是单行模式的内联标志) - 可匹配跨多行的
start到end之间的内容,例如:
start
中间换行
end
注意事项
- 不匹配换行符:默认情况下,
.*?不会匹配\n,若需包含换行符,需开启单行模式(re.DOTALL或s标志)。 - 性能问题:非贪婪匹配在复杂文本中可能比贪婪匹配稍慢,但可控,优先保证匹配准确性。
- 与其他量词结合:
?也可用于+(+?表示非贪婪匹配 1 次或多次)、{n,}({n,}?表示非贪婪匹配至少 n 次)等。
二、边界与位置匹配组合
- 单词边界
\b\w+\b:匹配完整单词(\b是单词边界,\w+匹配字母 / 数字 / 下划线)。- 示例:文本
hello world123中匹配hello和world123。
- 示例:文本
\B\w+\B:匹配非单词边界的字符(单词内部的字符)。- 示例:文本
hello中匹配ell(不含首尾字母)。
- 示例:文本
- 行首尾匹配
^...$:匹配整行内容(^行首,$行尾)。- 示例:
^hello$仅匹配单独一行的hello(排除hello world等)。
- 示例:
^#.\*$:匹配以#开头的行(如 Markdown 标题)。- 示例:匹配
# 标题或## 子标题。
- 示例:匹配
三、字符集与范围组合
- 自定义字符集
[a-zA-Z0-9_]:等价于\w,匹配字母、数字、下划线。[^a-zA-Z]:匹配非字母字符(^在字符集内表示 “非”)。- 示例:从
abc123!@中匹配123!@。
- 示例:从
[0-9a-fA-F]:匹配十六进制字符(0-9、a-f、A-F)。- 用途:验证颜色值(如
#ff0088)。
- 用途:验证颜色值(如
- 固定长度与范围
\d{3,4}-\d{7,8}:匹配固定格式的电话号码(如010-12345678或0571-8765432)。- 说明:
{3,4}表示 3-4 位数字,{7,8}表示 7-8 位数字。
- 说明:
\w{6,16}:匹配6-16 位的用户名(字母 / 数字 / 下划线)。
四、捕获与替换组合
- 分组捕获与引用
(\d{4})-(\d{2})-(\d{2}):捕获日期中的年、月、日(分组$1年,$2月,$3日)。- 替换示例:将
2023-10-01转为10/01/2023,替换规则为$2/$3/$1。
- 替换示例:将
(ab)+:捕获连续重复的ab(如ababab中匹配整个字符串,分组为ab)。
- 非捕获分组
(?:abc)+:匹配连续的abc,但不捕获分组(用于只匹配不提取的场景)。- 示例:
(?:abc){2}匹配abcabc,但替换时无法用$1引用。
- 示例:
五、特殊场景组合
- 邮箱验证
\w+([-+.]\w+)\*@\w+([-.]\w+)\*\.\w+([-.]\w+)\*- 解析:匹配常见邮箱格式(如
user.name+tag@domain.co.uk)。
- 解析:匹配常见邮箱格式(如
- URL 匹配
https?://[^\s]+- 含义:匹配
http://或https://开头,到第一个空白字符为止的 URL。 - 示例:匹配
https://example.com/path?query=1。
- 含义:匹配
- HTML/XML 标签提取
<[^>]+>:匹配任意 HTML/XML 标签(如<div>、<img src="x">)。- 用途:清除文本中的标签,替换为空即可。
- 多行匹配(需开启多行模式)
(?m)^#.\*$((?m)是多行模式内联标志)- 含义:在多行文本中,匹配每一行以
#开头的内容(如批量提取 Markdown 标题)。
- 含义:在多行文本中,匹配每一行以
- 包含换行符的匹配(单行模式)
(?s)start.\*?end((?s)是单行模式内联标志,让.匹配换行符)- 用途:匹配跨多行的内容,如:
start 中间换行内容 end
六、反义与排除组合
[^"]\*:匹配除双引号外的任意字符(用于提取引号内内容)。- 示例:
"hello world"中,用"([^"]*)"捕获hello world。
- 示例:
(?!ignore).\*:匹配不包含ignore的行(负向预查)。- 示例:
^(?!#).*$匹配非#开头的行(排除 Markdown 标题)。
- 示例:
总结
正则组合的核心是根据场景选择元字符 + 量词 + 模式:
- 匹配 “任意内容” 用
.*或.*?(控制贪婪 / 非贪婪); - 匹配 “特定格式”(如日期、邮箱)用字符集 + 固定长度;
- 处理 “结构化文本”(如标签、代码块)用分组 + 边界匹配;
- 复杂场景需结合模式修饰符(多行 / 单行模式)。