📌 软件教程

正则表达式从入门到精通完整教程:文本处理的利器

正则表达式怎么学?本教程从基础语法、常用模式、分组断言到实战案例,手把手教你掌握正则表达式,文本匹配验证提取一招搞定。

✍️ 口袋里的星星 🕒 2026-09-14 09:00 👁 25 阅读 📖 4,637 字 ⏱ 约 10 分钟

正则表达式从入门到精通完整教程:文本处理的利器

我以前看正则表达式就像看天书,一堆符号不知道什么意思。每次要验证邮箱、提取数据就搜半天,抄过来能用但不知道为什么。后来下决心系统学了一遍,发现其实没那么难,核心语法就那些。现在写正则很快,文本处理效率翻倍。今天把正则表达式从入门到实战的方法分享出来。

什么是正则表达式

正则表达式(Regular Expression,简称Regex)是一种文本匹配模式,用特殊语法描述字符串的规则。

用途:

1. 验证:邮箱格式对不对、手机号合不合法。

2. 提取:从文本中提取URL、电话号码。

3. 替换:批量替换文本中的内容。

4. 分割:按复杂规则分割字符串。

5. 搜索:在大量文本中找特定模式。

正则表达式几乎所有编程语言都支持,学会了一辈子受用。

基础语法

正则的核心是特殊字符(元字符)和普通字符的组合。

普通字符:字母、数字等,匹配自身。abc匹配abc。

元字符:有特殊含义的字符。

点号(.):匹配任意一个字符(除换行)。a.c匹配abc、a1c、a c。

星号(*):前面的出现0次或多次。ab*c匹配ac、abc、abbc。

加号(+):前面的出现1次或多次。ab+c匹配abc、abbc,不匹配ac。

问号(?):前面的出现0次或1次。colou?r匹配color和colour。

大括号({n,m}):前面的出现n到m次。a{2,4}匹配aa、aaa、aaaa。{n}恰好n次,{n,}至少n次。

方括号([]):匹配括号里任意一个字符。[abc]匹配a或b或c。[a-z]匹配任意小写字母。[0-9]匹配任意数字。[a-zA-Z0-9]匹配字母数字。

脱字符(^):在[]里表示"非"。[^abc]匹配不是a/b/c的字符。在[]外表示行首。^Hello匹配以Hello开头的行。

美元符($):表示行尾。world$匹配以world结尾的行。

反斜杠():转义元字符或表示特殊序列。匹配实际的点号,*匹配实际的星号。

竖线(|):或。cat|dog匹配cat或dog。

圆括号(()):分组。(ab)+匹配ab、abab、ababab。也用于提取捕获组。

这些是基础,记住这些已经能写很多正则了。

特殊字符序列

以反斜杠开头的特殊序列,代表某类字符:

d:数字,等价[0-9]。

D:非数字,等价[^0-9]。

w:字母数字下划线,等价[a-zA-Z0-9_]。

W:非字母数字下划线。

s:空白字符(空格、Tab、换行)。

S:非空白字符。

:单词边界。word匹配完整的word,不匹配password里的word。

B:非单词边界。

:换行符。 :Tab。 :回车。

这些用起来比方括号简洁。d+匹配数字,w+匹配单词。

量词详解

量词控制前面元素出现的次数。

*:0次或多次。等价{0,}。

+:1次或多次。等价{1,}。

?:0次或1次。等价{0,1}。

{n}:恰好n次。

{n,}:至少n次。

{n,m}:n到m次。

贪婪与非贪婪:

默认贪婪:尽可能多匹配。a.*b对"aabbb"匹配"aabbb"(从第一个a到最后一个b)。

非贪婪(加?):尽可能少匹配。a.*?b对"aabbb"匹配"aab"(从第一个a到第一个b)。

*?、+?、??、{n,m}?都是非贪婪版本。

我提取HTML标签内容时用非贪婪,不然会匹配过多。

分组与捕获

圆括号不只分组,还能捕获匹配内容。

(abc):捕获组,匹配abc并保存。可以用$1(或1)引用第一个捕获组。

例子:把日期2026-09-14改成14/09/2026。正则(d{4})-(d{2})-(d{2})替换为$3/$2/$1。$1是年份,$2是月份,$3是日期。

(?:abc):非捕获组,只分组不捕获。不占用$编号,性能稍好。

(?P<name>abc):命名捕获组(Python语法)。用名字引用,比数字清晰。

分组嵌套:外到内、左到右编号。(a(b(c))),$1是abc,$2是bc,$3是c。

我用捕获组做数据提取和替换,很方便。

零宽断言

断言(Lookaround)匹配位置但不消费字符,像条件判断。

正向先行断言(?=...):后面跟着什么。abc(?=def)匹配abc,但abc后面必须是def。

负向先行断言(?!...):后面不跟着什么。abc(?!def)匹配abc,但abc后面不能是def。

正向后行断言(?<=...):前面是什么。(?<=abc)def匹配def,但def前面必须是abc。

负向后行断言(?<!...):前面不是什么。(?<!abc)def匹配def,但def前面不能是abc。

断言不消耗字符,匹配的是位置。我提取价格数字时用(?<=¥)d+,匹配¥后面的数字但不包括¥。

标志位

正则后面的标志位控制匹配方式:

g:全局匹配,找所有匹配,不只是第一个。

i:忽略大小写。

m:多行模式,^和$匹配每行的行首行尾。

s:单行模式,.也匹配换行符。

u:Unicode模式,正确处理中文等。

y:粘连模式,从lastIndex开始匹配。

JavaScript里/abc/gi,Python里re.findall(pattern, string, re.I)。

常用正则模式

收集一些常用的:

邮箱:^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$

手机号(中国):^1[3-9]d{9}$

身份证号(18位):^d{17}[dXx]$

URL:^https?://[w.-]+(.[w.-]+)+.*$

IP地址:^(d{1,3}.){3}d{1,3}$(简单版)

日期(YYYY-MM-DD):^d{4}-d{2}-d{2}$

时间(HH:MM:SS):^([01]d|2[0-3]):[0-5]d:[0-5]d$

邮编:^d{6}$

QQ号:^[1-9]d{4,10}$

密码强度(8位以上含大小写数字特殊字符):^(?=.*[a-z])(?=.*[A-Z])(?=.*d)(?=.*[@$!%*?&]).{8,}$

中文字符:[u4e00-u9fa5]

HTML标签:<[^>]+>

这些模式存起来,需要直接用。但要根据实际需求调整,别盲目抄。

实战案例

案例一:验证表单输入

用户注册时验证邮箱、手机号、密码。用正则一行搞定。

JavaScript:

const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/;

if (emailRegex.test(email)) { // 合法 }

Python:

import re

if re.match(r"^1[3-9]d{9}$", phone):

print("合法")

案例二:从文本提取数据

从一段文本提取所有URL:

Python:urls = re.findall(r"https?://[w./-]+", text)

JavaScript:const urls = text.match(/https?://[w./-]+/g)

提取所有邮箱:

emails = re.findall(r"[w.+-]+@[w-]+.[w.]+", text)

案例三:批量替换

把文本中的手机号中间4位打码:138****8888。

Python:re.sub(r"(1[3-9]d)d{4}(d{4})", r"1****2", text)

JavaScript:text.replace(/(1[3-9]d)d{4}(d{4})/g, "$1****$2")

把HTML标签去掉:

text.replace(/<[^>]+>/g, "")

案例四:日志分析

从Nginx日志提取IP和访问路径:

日志格式:192.168.1.1 - - [10/Sep/2026:09:00:00] "GET /index.html HTTP/1.1" 200

正则:^(d+.d+.d+.d+).*"(GET|POST) (S+)"

$1是IP,$2是方法,$3是路径。

案例五:数据清洗

提取CSV中的引号包裹字段:

"name","age","city"

正则:"([^"]*)"提取引号内的内容。

我用正则做数据清洗,省了大量手动处理时间。

正则测试工具

写正则别在脑子里想,用工具测试。

1. regex101.com:最强的在线正则测试工具,支持多种语言,有解释。我常用。

2. regexr.com:另一个在线工具。

3. VS Code搜索支持正则(Alt+R或点.*图标)。

4. 各语言的正则模块:Python的re、JavaScript的RegExp。

我写正则的流程:在regex101上测试通过,再写到代码里。

各语言正则差异

不同语言正则语法略有差异:

JavaScript:/pattern/flags或new RegExp()。replace用$1引用组。

Python:re模块。re.match(从头)、re.search(任意位置)、re.findall(找所有)、re.sub(替换)、re.split(分割)。组引用1或g<name>。

Java:java.util.regex包。Pattern和Matcher。组引用$1。

PHP:preg_match、preg_replace。组引用$1或1。

Go:regexp包。反引号正则字符串。

grep:命令行正则搜索。grep -E "pattern" file。扩展正则。

各语言核心语法一样,细节有差异,查文档确认。

性能优化

正则写不好会慢,甚至导致灾难性回溯(ReDoS)。

优化技巧:

1. 避免嵌套量词:(a+)+这种容易回溯爆炸。

2. 用具体字符代替.:用[^"\]代替.*匹配字符串内容。

3. 用非捕获组(?:):不捕获不用的组。

4. 锚定^$:减少匹配范围。

5. 避免回溯:用原子组(?>...)或占有量词?+(部分语言支持)。

6. 编译正则:循环里用预编译的正则,别每次重新编译。Python用re.compile。

7. 能用字符串方法就用字符串方法:startsWith、includes比正则快。

学习建议

正则学习路径:

1. 先学基础语法:. * + ? [] ^ $ d w s。

2. 学量词和分组:{} ()。

3. 学断言:?= ?! ?<= ?<!

4. 在regex101练习。

5. 收集常用模式。

6. 实战中用,用多了就会了。

别想一次全记住,用的时候查,用多了自然记住。我用了两年,常用语法都在脑子里了。

常见坑

1. 贪婪匹配:.*会匹配过多。用.*?非贪婪。

2. 忘记转义:匹配实际的.要写.,匹配?要写?。

3. 锚定忘记:不加^$可能部分匹配。"123"用d+会匹配,但"abc123"也会匹配里面的123。要验证整个字符串用^d+$。

4. 中文匹配:w不匹配中文,用[u4e00-u9fa5]或u标志。

5. 转义在字符串里:Python r"d"和"d"不同,r""原始字符串不用双重转义。JavaScript字符串里d要写成\d。

我的正则使用习惯

1. 先在regex101测试,再写代码。

2. 加注释说明正则含义(复杂正则可读性差)。

3. 收集常用模式存笔记。

4. 性能敏感场景测试正则速度。

5. 能用字符串方法就不滥用正则。

正则用好了是利器,用不好是灾难。多练多用,自然熟练。

总结

正则表达式看着吓人,其实核心语法不多。基础语法+量词+分组+断言,掌握这些日常够用。关键是多练多用,在regex101上测试,实战中积累。学会正则,文本处理效率翻倍,验证、提取、替换一招搞定。这是程序员受益一生的技能。

🔠 字号

看累了?去工具区松一松 🧘

白噪音、深呼吸、三分钟小游戏,满血复活再回来。