1_1、 正则表达式 - 指南
正则表达式
1. 简介
正则表达式(Regular Expression,简称Regex 或 RegExp一种用于描述、匹配和处理文本模式的就是)特殊字符串规则。它通过预定义的符号和语法,飞快从复杂文本中筛选、验证、提取或替换符合特定格式的内容,是编程、文本处理、数据清洗等场景的核心工具。
方便来说,正则表达式的核心价值是用一套简洁的规则,替代繁琐的字符串判断逻辑。比如:
- 验证“手机号是否为11位数字”
- 从文本中提取所有“邮箱地址”
- 将所有“日期格式(2024-05-20)”替换为“2024年05月20日”
- 过滤文本中的所有“HTML标签”
没有正则表达式时,需要写大量代码判断字符类型、长度、位置;有了正则,一行规则即可完成。
2. 基本语法:符号即规则
正则表达式的语法由“普通字符”和“元字符”组成,元字符是实现“模式匹配”的核心,常用元字符可分为以下几类:
2.1 匹配“单个字符”的元字符
| 元字符 | 含义 | 示例 |
|---|---|---|
. | 匹配任意单个字符(除换行符 \n) | a.b 可匹配 aab、acb、a1b(中间是任意字符) |
[ ] | 匹配“括号内任意一个字符” | [0-9] 匹配单个数字;[a-zA-Z] 匹配单个字母 |
[^ ] | 匹配“非括号内的任意字符” | [^0-9] 匹配非数字(如字母、符号) |
\d | 等价于 [0-9],匹配单个数字 | \d{3} 匹配 3 个连续数字(如 123) |
\D | 等价于 [^0-9],匹配非数字 | \D 可匹配 a、!、(空格) |
\w | 匹配“字母、数字、下划线”(等价于 [a-zA-Z0-9_]) | \w 可匹配 A、5、_ |
\W | 匹配“非字母、非数字、非下划线” | \W 可匹配 @、#、(空格) |
\s | 匹配“空白字符”(空格、制表符 \t、换行符 \n 等) | a\sb 可匹配 a b(中间是空格)、a\tb(中间是制表符) |
2.2 控制“匹配次数”的元字符
用于指定某个字符/子模式的重复次数,处理“多字符匹配”问题:
| 元字符 | 含义 | 示例 |
|---|---|---|
* | 匹配前一个元素“0次或多次”(贪婪:尽可能多匹配) | a* 可匹配 ""(空)、a、aa、aaa |
+ | 匹配前一个元素“1次或多次”(贪婪) | a+ 可匹配 a、aa,但不匹配空 |
? | 匹配前一个元素“0次或1次”(可选) | ab? 可匹配 a(b出现0次)、ab(b出现1次) |
{n} | 匹配前一个元素“恰好n次” | \d{4} 匹配 4 个数字(如 2024,用于匹配年份) |
{n,} | 匹配前一个元素“至少n次” | \d{2,} 可匹配 12、123、1234 |
{n,m} | 匹配前一个元素“n到m次” | \d{3,4} 可匹配 123(3次)、1234(4次) |
*?/+? | 非贪婪模式(尽可能少匹配) | 对 aabbaa 用 a.*?a,会匹配 aabba(而非全串) |
2.3 控制“位置”的元字符
用于锁定匹配内容在文本中的位置(开头、结尾、单词边界等):
| 元字符 | 含义 | 示例 |
|---|---|---|
^ | 匹配“字符串开头”(多行模式下匹配“每行开头”) | ^Hello 可匹配 Hello World(开头是Hello),不匹配 Hi Hello |
$ | 匹配“字符串结尾”(多行模式下匹配“每行结尾”) | World$ 可匹配 Hello World(结尾是World),不匹配 World Hi |
\b | 匹配“单词边界”(字母/数字与非字母/数字的分隔处) | \bcat\b 可匹配 cat(单独单词),不匹配 category(cat是前缀) |
\B | 匹配“非单词边界” | \Bcat\B 可匹配 category(cat在单词中间),不匹配单独的 cat |
2.4 分组与逻辑:处理复杂模式
当需要匹配“多个子模式的组合”时,用分组和逻辑符号:
| 元字符 | 含义 | 示例 |
|---|---|---|
( ) | 分组:将多个字符视为一个整体,且可“捕获”匹配结果 | (ab)+ 可匹配 ab、abab(ab重复1次或多次);(\d{4})-(\d{2}) 可捕获“年”和“月” |
| 1(竖线) | 逻辑“或”:匹配多个模式中的一个 | cat1dog 可匹配 cat 或 dog |
\n | 引用第n个分组的匹配结果(反向引用) | (\w+)\s+\1 可匹配重复单词(如 hello hello,\1 引用第一个分组的 hello) |
3. 典型应用场景(附示例)
正则表达式的用法本质是“用规则匹配文本”,以下是最常见的场景:
3.1 文本验证(格式合法性判断)
否符合特定格式(如手机号、邮箱、身份证):就是验证输入
验证中国大陆手机号“1开头,第二位3-9,后面9位数字”就是:规则
正则:^1[3-9]\d{9}$
匹配:13812345678(有效);不匹配:12345678901(第二位是2,无效)验证邮箱:规则是“用户名@域名.后缀”(简化版)
正则:^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$
匹配:test@example.com(有效);不匹配:test@.com(域名无效)
3.2 内容提取(从文本中抓指定信息)
从杂乱文本中提取符合规则的内容(如日期、URL):
提取所有日期(格式:2024-05-20)
正则:\d{4}-\d{2}-\d{2}
文本:今天是2024-05-20,昨天是2024-05-19
提取结果:2024-05-20、2024-05-19提取URL中的域名
正则:https?://(www\.)?([^/]+)(https?匹配http或https;([^/]+)捕获域名)
文本:访问 https://www.qt.io/doc/ 查看文档
提取结果:qt.io(第二个分组的内容)
3.3 文本替换(批量修改内容)
按规则替换文本中的特定部分(如敏感词过滤、格式转换):
过滤敏感词“bad”
正则:bad(可加i选项不区分大小写,如bad/i)
文本:This is a bad word, BAD!
替换为***后:This is a *** word, ***!将日期“2024-05-20”改为“2024年05月20日”
正则:(\d{4})-(\d{2})-(\d{2})(分组捕获年、月、日)
替换规则:$1年$2月$3日($1引用第一个分组的“年”,以此类推)
替换后:2024年05月20日
3.4 文本分割(按复杂规则拆分)
按“非固定分隔符”拆分文本(如同时按逗号、分号、空格拆分):
- 正则:
[,;\\s]+([,;]匹配逗号或分号;\s匹配空格;+表示“一个或多个”)
文本:apple, banana; orange grape
分割结果:["apple", "banana", "orange", "grape"]
4. 总结
4.1 注意事项
转义字符挑战:在编程语言(如C++、Java)中,
\是转义符,因此正则中的\d需写成\\d(双重转义)。例如在C++中,匹配数字的正则要写为"\\d",而非"\d"。贪婪与非贪婪:
*、+默认是“贪婪模式”(尽可能多匹配),如需“非贪婪”(尽可能少匹配),需在后面加?。例如:- 文本:
aabbaa - 贪婪匹配
a.*a:会匹配整个字符串aabbaa(从第一个a到最后一个a) - 非贪婪匹配
a.*?a:会匹配aabba(从第一个a到最近的a)
- 文本:
性能考量:复杂正则(如多层嵌套、大量通配符)在处理超长文本时可能效率较低,建议:
- 尽量用具体规则替代模糊规则(如用
[0-9]而非.匹配数字) - 避免不必要的分组和回溯(如用
{3}替代???)
- 尽量用具体规则替代模糊规则(如用
工具辅助:正则语法较抽象,推荐用在线工具调试(如Regex101、Regexr),输入规则和测试文本即可实时查看匹配结果。
4.2 跨语言通用性
正则表达式的核心语法是通用的(如元字符 .、*、\d 等),但不同编程语言(C++、Python、Java、JavaScript)的“语法细节”和“支持的高级特性”略有差异:
- C++:通过
QRegExp(Qt)或std::regex(C++11+)实现 - Python:通过内置
re模块实现 - JavaScript:通过
RegExp对象或字面量(如/\d+/)实现
但只要掌握核心语法,切换语言时只需调整“语法细节”(如转义方式、函数调用)即可。
“文本处理的瑞士军刀”——学会它,能极大提升文本处理的效率和灵活性。就是总之,正则表达式
浙公网安备 33010602011771号