正则表达式(Regular Expression,简称 regex 或 regexp)是一种用来匹配、查找、替换文本的强大工具,广泛用于编程、文本处理、数据验证等场景(如验证邮箱格式、提取日志内容、清洗数据等)。下面从基础到进阶,带你快速掌握核心用法:
一、基础概念:字符与匹配规则
正则表达式通过元字符(有特殊含义的字符)和普通字符(如字母、数字)的组合,描述文本的“模式”。
1. 普通字符:精确匹配
普通字符(如 a、123、hello)会精确匹配自身。
示例:正则 cat 会匹配文本中的 cat 子串(如 cat、category 中的 cat)。
2. 元字符:特殊含义的字符
元字符是正则的“核心语法”,常用元字符及含义:
| 元字符 | 含义 | 示例 | 匹配效果 |
|---|---|---|---|
. |
匹配任意单个字符(除换行符 \n,若开启多行模式也可匹配换行)。 |
a.c |
匹配 abc、a1c、a&c 等 |
* |
匹配前面的字符/子模式 0 次或多次(贪婪匹配,尽可能多匹配)。 | ab*c |
匹配 ac、abc、abbbbbc
|
+ |
匹配前面的字符/子模式 1 次或多次(贪婪匹配)。 | ab+c |
匹配 abc、abbbbbc,不匹配 ac
|
? |
匹配前面的字符/子模式 0 次或 1 次;也可用于“非贪婪匹配”(加在 */+ 后)。 |
ab?c a.*?c
|
匹配 ac、abc 匹配 a 和 c 之间最短的内容(如 abc 中取 abc,a123c 中取 a123c 里的最短部分) |
{n} |
匹配前面的字符/子模式恰好 n 次。 | a{3} |
匹配 aaa
|
{n,} |
匹配前面的字符/子模式至少 n 次。 | a{2,} |
匹配 aa、aaa、aaaa...
|
{n,m} |
匹配前面的字符/子模式至少 n 次,最多 m 次。 | a{1,3} |
匹配 a、aa、aaa
|
[] |
字符类:匹配括号内的任意单个字符;也可表示范围。 |
[abc] [0-9]
|
匹配 a/b/c 匹配 0-9 的数字 |
[^] |
否定字符类:匹配不在括号内的任意单个字符。 | [^0-9] |
匹配非数字字符(如字母、符号) |
^ |
锚定符:匹配行的开头(若开启多行模式,匹配每一行的开头)。 | ^Hello |
匹配以 Hello 开头的行 |
$ |
锚定符:匹配行的结尾(若开启多行模式,匹配每一行的结尾)。 | end$ |
匹配以 end 结尾的行 |
() |
分组:将多个字符/子模式视为一个整体,可用于“捕获”或“或操作”。 |
(abc)+ `(a |
b)c` |
| ` | ` | 或操作:匹配左边或右边的子模式。 | `cat |
\ |
转义符:将元字符转义为“普通字符”(如匹配 * 本身需写 \*);也用于预定义字符类(如 \d)。 |
\* \d
|
匹配 * 匹配数字(同 [0-9]) |
3. 预定义字符类(简化版字符范围)
正则提供了一些简写符号,代替常用的字符范围:
| 预定义类 | 等价写法 | 含义 |
|---|---|---|
\d |
[0-9] |
匹配数字 |
\D |
[^0-9] |
匹配非数字 |
\w |
[a-zA-Z0-9_] |
匹配“单词字符”(字母、数字、下划线) |
\W |
[^a-zA-Z0-9_] |
匹配非单词字符 |
\s |
[ \t\n\r\f\v] |
匹配空白字符(空格、制表符、换行等) |
\S |
[^ \t\n\r\f\v] |
匹配非空白字符 |
二、进阶用法:分组、捕获与非贪婪匹配
1. 分组与捕获(() 的作用)
-
分组:将多个字符视为一个整体,配合量词使用。
示例:(ab)+匹配ab、abab、ababab…(ab作为整体重复)。 -
捕获:分组会“记住”匹配的内容,可通过反向引用(
\1、\2…)在后续复用。
示例:正则(\w+) \1匹配“重复的单词”(如hello hello),\1表示引用第一个分组(\w+)匹配的内容。
2. 非贪婪匹配(? 的另一种用法)
正则默认是贪婪匹配(尽可能多匹配),加 ? 可改为非贪婪匹配(尽可能少匹配)。
示例:
- 贪婪:
a.*c匹配a123c456c时,会匹配a123c456c(从第一个a到最后一个c)。 - 非贪婪:
a.*?c匹配a123c456c时,会匹配a123c(从第一个a到最近的c)。
三、实战示例:常见场景的正则
1. 验证邮箱格式
需求:匹配常见邮箱(如 user@example.***、info123@mail.***)。
正则:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
解释:
-
^\w+:开头是“单词字符”(用户名开头)。 -
([-+.]\w+)*:用户名中可包含-、+、.,且后面跟“单词字符”,重复 0 次或多次。 -
@:匹配@符号。 -
\w+([-.]\w+)*:域名前缀(如example),可包含-、.。 -
\.\w+([-.]\w+)*:域名后缀(如.***、.co.uk),以.开头,后跟“单词字符”及可选的-/.。
2. 提取 URL 中的域名
需求:从 https://www.example.***/path?query 中提取 www.example.***。
正则:://([^/]+)
解释:
-
://:匹配://固定字符。 -
([^/]+):捕获“非/的字符”(直到遇到下一个/为止),即域名部分。
在正则://([^/]+)中,://是直接匹配 URL 中固定存在的字符串“😕/”,作用是精准定位到域名的起始位置,避免误匹配其他内容。
具体解释:
我们目标是从 URL(如 https://www.example.***/path?query)中提取 www.example.***,而 URL 的结构通常是:
协议://域名/路径?参数
(比如 https://www.example.***/path?query 中,https 是协议,www.example.*** 是域名,/path 是路径)
:// 的核心作用:
它是协议和域名之间的固定分隔符(比如 http://、https://、ftp:// 中都有 ://)。
正则中先写 ://,就是为了跳过前面的“协议部分”(如 https),直接定位到 :// 后面的内容——这部分才是域名的起始位置。
举例说明:
在 https://www.example.***/path?query 中:
- 正则
://会精准匹配https后面的://这三个字符; - 紧接着的
([^/]+)就会从://之后开始匹配(即从www.example.***的第一个字符w开始),直到遇到第一个/为止(www.example.***后面的/),最终捕获www.example.***。
如果没有 ://,直接用 ([^/]+),会匹配什么?
会从 URL 开头开始匹配非 / 的字符,结果会误把 https 也包含进去(比如匹配 https),无法准确定位到域名。
所以,:// 是通过匹配固定分隔符,帮我们“锚定”到域名的起始位置,确保后续的 ([^/]+) 只捕获域名部分。
([^/]+) 是正则中用于精准捕获域名的核心部分,我们拆解来看它的作用:
1. 先看 [^/]:否定字符类,匹配“非 / 的任意字符”
-
[]表示“字符类”,里面的内容是“允许匹配的字符范围”; -
^放在[]开头时,表示“否定”——即[^/]表示“匹配任何不是/的字符”(比如字母、数字、.、-、www中的w等,只要不是/都能匹配)。
2. 再看 +:量词,匹配“前面的元素 1 次或多次”
+ 在这里修饰 [^/],表示“连续的、非 / 的字符,至少出现 1 次,最多可以出现任意多次”(只要这些字符中间没有 / 打断)。
3. 整体 ([^/]+):捕获“连续的非 / 字符”
- 括号
()是“捕获分组”,作用是把匹配到的内容单独“拎出来”(后续可以提取这个分组的结果,也就是我们要的域名); - 结合起来,
([^/]+)会从当前位置开始,连续匹配所有不是/的字符,直到遇到第一个/为止,然后把这些字符作为一个“分组”捕获下来。
结合 URL 实例看效果
以 https://www.example.***/path?query 为例:
- 前面的
://已经匹配了https后面的://,接下来就轮到([^/]+)工作; - 从
://之后的第一个字符(w)开始,[^/]会匹配w、w、w、.、e、x……直到遇到www.example.***后面的/(即/path中的/); - 因为
+要求“至少 1 次”,所以会把www.example.***这一串连续的非/字符全部匹配,并用括号捕获——这正是我们需要的域名。
为什么这样写能精准定位域名?
因为 URL 的结构是固定的:协议://域名/路径?参数,其中域名的后面一定跟着第一个 /(比如 www.example.*** 后面是 /path)。
[^/]+ 刚好利用这一点,“贪婪”地匹配所有到第一个 / 为止的非 / 字符,完美圈定域名范围。
如果没有 [^/],比如直接用 .+(匹配任意字符多次),就会把 /path?query 也一起匹配进去,无法单独提取域名。
3. 匹配手机号(以中国大陆为例)
需求:匹配 11 位手机号,开头为 1,第二位为 3/4/5/6/7/8/9。
正则:^1[3-9]\d{9}$
解释:
-
^1:开头是1。 -
[3-9]:第二位是 3-9 中的一个数字。 -
\d{9}:后面跟 9 位数字。 -
$:行结尾,确保总长度为 11 位。
四、工具推荐:快速测试正则
学习正则时,建议用在线测试工具实时验证效果:
- regex101:支持多种语言(Python、JavaScript 等),提供详细匹配说明、错误提示。
- RegExr:可视化正则分组、字符类,适合新手理解。
五、学习建议
-
从简单到复杂:先掌握单个元字符(如
.、*、[]),再组合成复杂模式。 - 多实战:找一段文本(如日志、网页源码),用正则尝试匹配、提取目标内容。
- 善用工具:用在线工具测试正则,观察匹配过程,理解每一步的作用。
通过以上内容,你已经掌握了正则表达式的核心语法和常见用法,接下来就可以在实际场景中练习啦~
补充:
正则表达式里的 *、+、? 都属于**“量词元字符”**,用来规定“前面的字符/子表达式出现的次数”,具体含义和示例如下:
1. *(星号)
匹配 前面的字符/子表达式 “0次或多次”(可以不出现,也能出现任意多次)。
示例:
正则 ab*c 中,b 可出现 0 次、1 次或多次,因此能匹配:
-
ac(b出现 0 次); -
abc(b出现 1 次); -
abbbbbc(b出现多次)。
2. +(加号)
匹配 前面的字符/子表达式 “1次或多次”(至少出现 1 次,不能不出现)。
示例:
正则 ab+c 中,b 至少出现 1 次,因此能匹配:
-
abc(b出现 1 次); -
abbbbbc(b出现多次);
但 不匹配ac(b出现 0 次)。
3. ?(问号)
匹配 前面的字符/子表达式 “0次或1次”(最多出现 1 次,要么没有,要么只有 1 次)。
示例:
正则 ab?c 中,b 最多出现 1 次,因此能匹配:
-
ac(b出现 0 次); -
abc(b出现 1 次);
但 不匹配abbc(b出现 2 次)。
简单记忆:
-
*→ “可有可无,多了也能要”; -
+→ “至少有 1 个”; -
?→ “最多 1 个,没有也可以”。