一、什么是正则表达式?
正则表达式(Regular Expression)是一种强大的文本匹配模式,用于检索、验证或替换符合特定规则的字符串。
1.1 正则表达式能做什么?
1 2 3 4 5 6 7 8 9 10
| ┌─────────────────────────────────────────────────────────────────┐ │ 正则表达式用途 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 🔍 验证 → 邮箱、手机号、身份证等格式验证 │ │ 🔎 搜索 → 从大量文本中提取需要的内容 │ │ 🔄 替换 → 批量修改、格式化文本 │ │ 📝 提取 → 提取URL、标签、数字等特定内容 │ │ │ └─────────────────────────────────────────────────────────────────┘
|
1.2 常见使用场景
| 场景 |
示例 |
| 表单验证 |
邮箱、手机号、密码强度 |
| 数据提取 |
从日志中提取时间、IP |
| 文本替换 |
批量格式化、清理数据 |
| 爬虫 |
提取网页中的链接、图片 |
二、基础语法
2.1 元字符
| 元字符 |
说明 |
示例 |
. |
任意单个字符(除换行) |
a.c → abc, aXc |
\d |
任意数字 |
\d → 1, 9 |
\D |
任意非数字 |
\D → a, @ |
\w |
字母、数字、下划线 |
\w+ → hello_123 |
\W |
非字母数字下划线 |
\W → @, # |
\s |
空白字符(空格 tab 换行) |
\s+ → 空格 |
\S |
非空白字符 |
\S+ → hello |
\b |
单词边界 |
\bhello\b |
\B |
非单词边界 |
|
^ |
字符串开头 |
^hello |
$ |
字符串结尾 |
world$ |
2.2 字符类
1 2 3 4 5 6 7
| [abc] # 匹配a、b、c中的任意一个 [^abc] # 匹配除了a、b、c的任意字符 [a-z] # 匹配a到z的任意字符 [A-Z] # 匹配A到Z [0-9] # 匹配0到9 [a-zA-Z] # 匹配所有字母 [a-zA-Z0-9] # 匹配字母和数字
|
示例:
1 2 3
| [aeiou] # 匹配元音字母 [0-9]{3} # 匹配3位数字 [a-zA-Z]{3,} # 至少3个字母
|
2.3 量词
| 量词 |
说明 |
示例 |
* |
0次或多次 |
ab* → a, ab, abb |
+ |
1次或多次 |
ab+ → ab, abb |
? |
0次或1次 |
ab? → a, ab |
{n} |
恰好n次 |
a{3} → aaa |
{n,} |
至少n次 |
a{2,} → aa, aaa |
{n,m} |
n到m次 |
a{2,4} → aa, aaa, aaaa |
*? |
0次或多次(非贪婪) |
|
+? |
1次或多次(非贪婪) |
|
三、常用正则表达式
3.1 数字相关
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| # 整数 ^-?\d+$
# 正整数 ^[1-9]\d*$
# 负整数 ^-[1-9]\d*$
# 浮点数 ^-?\d+\.\d+$
# 正浮点数 ^[1-9]\d*\.\d+$|^0\.\d+[1-9]$
# 数字(可带千分位) ^[\d,]+$
# 货币金额(两位小数) ^\d{1,3}(,\d{3})*(\.\d{2})?$
|
3.2 中文相关
1 2 3 4 5 6 7 8 9 10 11
| # 中文汉字 [\u4e00-\u9fa5]
# 中文姓名(2-4个汉字) ^[\u4e00-\u9fa5]{2,4}$
# 中文地址 [\u4e00-\u9fa5]+省[\u4e00-\u9fa5]+市[\u4e00-\u9fa5]+区
# 中文句子 [\u4e00-\u9fa5]+
|
3.3 英文相关
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| # 纯英文 ^[a-zA-Z]+$
# 英文和数字 ^[a-zA-Z0-9]+$
# 小写英文 ^[a-z]+$
# 大写英文 ^[A-Z]+$
# 英文、数字、下划线 ^[a-zA-Z0-9_]+$
|
3.4 联系方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| # 中国手机号 ^1[3-9]\d{9}$
# 固定电话 ^0\d{2,3}-?\d{7,8}$
# 中国身份证号(18位) ^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$
# 邮箱 ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
# QQ号 ^[1-9]\d{4,10}$
# 微信号 ^[a-zA-Z][a-zA-Z0-9_-]{5,19}$
|
3.5 URL与域名
1 2 3 4 5 6 7 8 9 10 11
| # HTTP/HTTPS URL ^https?:\/\/([\w\-]+\.)+[\w\-]+(\/[\w\-\.~!@#$%^&*+?:\\\[\]=.;,':"/\\|]*)?$
# 域名 ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z]{2,})+$
# IP地址 ^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$
# IPv6地址 ^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$
|
3.6 日期与时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| # 日期(YYYY-MM-DD) ^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
# 日期(YYYY/MM/DD) ^\d{4}\/(0[1-9]|1[0-2])\/(0[1-9]|[12]\d|3[01])$
# 日期(YYYYMMDD) ^\d{8}$
# 时间(HH:MM:SS) ^([01]\d|2[0-3]):[0-5]\d:[0-5]\d$
# 时间(HH:MM) ^([01]\d|2[0-3]):[0-5]\d$
# 日期时间(ISO格式) ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z?$
|
3.7 密码验证
1 2 3 4 5 6 7 8
| # 密码(6-18位,字母数字) ^[a-zA-Z0-9]{6,18}$
# 密码(必须包含字母和数字) ^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$
# 密码(必须包含大小写字母、数字、特殊字符) ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$
|
3.8 HTML相关
1 2 3 4 5 6 7 8 9 10 11
| # HTML标签 <([a-z]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)
# HTML标签(简化) <[^>]+>
# 图片标签 <img\s+[^>]*src=["']([^"']+)["'][^>]*>
# 链接标签 <a\s+[^>]*href=["']([^"']+)["'][^>]*>([^<]+)<\/a>
|
四、Python中使用正则
4.1 基本操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import re
pattern = r'\d+' text = 'abc123def456' result = re.search(pattern, text) print(result.group())
result = re.findall(r'\d+', text) print(result)
result = re.sub(r'\d+', 'X', text) print(result)
result = re.split(r'\d+', text) print(result)
|
4.2 匹配对象
1 2 3 4 5 6 7 8 9 10 11 12 13
| import re
pattern = r'(\d{4})-(\d{2})-(\d{2})' text = '2026-02-13'
match = re.search(pattern, text) if match: print(match.group()) print(match.group(1)) print(match.group(2)) print(match.group(3)) print(match.groups()) print(match.span())
|
4.3 编译正则
1 2 3 4 5 6 7 8
| import re
pattern = re.compile(r'\d{4}-\d{2}-\d{2}')
result = pattern.findall('2026-02-13 2025-01-01') print(result)
|
4.4 命名分组
1 2 3 4 5 6 7 8 9 10
| import re
pattern = r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})' text = '2026-02-13'
match = re.search(pattern, text) print(match.group('year')) print(match.group('month')) print(match.group('day')) print(match.groupdict())
|
4.5 实战示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import re
emails = 'test@example.com, user@domain.org, invalid@' result = re.findall(r'[\w.-]+@[\w.-]+\.\w+', emails) print(result)
text = '访问 https://example.com 和 http://test.org' result = re.findall(r'https?://[\w\-.]+', text) print(result)
phone = '13812345678' pattern = r'^1[3-9]\d{9}$' if re.match(pattern, phone): print('有效手机号')
html = '<a href="https://example.com">点击</a>' result = re.search(r'href=["\']([^"\']+)["\'][^>]*>([^<]+)<', html) if result: print(result.group(1)) print(result.group(2))
date = '2026/02/13' result = re.sub(r'(\d{4})/(\d{2})/(\d{2})', r'\1-\2-\3', date) print(result)
|
五、JavaScript中使用正则
5.1 基本操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| const pattern = /\d+/; const pattern2 = new RegExp('\\d+');
const str = 'abc123'; console.log(/\d+/.test(str));
const result = /\d+/.exec(str); console.log(result[0]);
console.log('abc123def456'.match(/\d+/g));
console.log('abc123'.replace(/\d+/, 'X'));
console.log('a1b2c'.split(/\d+/));
|
5.2 常用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| function validateEmail(email) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); }
function validatePhone(phone) { return /^1[3-9]\d{9}$/.test(phone); }
const text = '访问 https://example.com 和 http://test.org'; const urls = text.match(/https?:\/\/[\w\-.]+/g); console.log(urls);
const dateStr = '2026-02-13'; const [, year, month, day] = dateStr.match(/(\d{4})-(\d{2})-(\d{2})/); console.log(year, month, day);
function formatPhone(phone) { return phone.replace(/(\d{3})(\d{4})(\d{4})/, '$1****$3'); } console.log(formatPhone('13812345678'));
function stripTags(html) { return html.replace(/<[^>]+>/g, ''); } console.log(stripTags('<p>Hello</p>'));
|
5.3 零宽断言
1 2 3 4 5 6 7 8 9 10 11
| console.log('a1b2c3'.replace(/\d(?=[a-z])/g, 'X'));
console.log('a1b2c3'.replace(/\d(?![a-z])/g, 'X'));
console.log('a1b2c3'.replace(/(?<=[a-z])\d/g, 'X'));
console.log('a1b2c3'.replace(/(?<![a-z])\d/g, 'X'));
|
六、Linux命令行中使用
6.1 grep
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| grep "error" log.txt
grep -E "\d{4}-\d{2}-\d{2}" log.txt
grep -n "error" log.txt
grep -v "debug" log.txt
grep -A 3 "error" log.txt
grep -B 3 "error" log.txt
grep -C 3 "error" log.txt
grep -i "error" log.txt
grep -r "error" /var/log/
grep -l "error" *.txt
|
6.2 sed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| sed 's/old/new/' file.txt
sed 's/old/new/g' file.txt
sed '5s/old/new/' file.txt
sed '1,5s/old/new/g' file.txt
sed '/error/d' file.txt
sed -n '1,10p' file.txt
sed '1i\Header' file.txt
sed '1a\New line' file.txt
|
6.3 awk
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| awk '{print $1}' file.txt
awk -F',' '{print $1}' file.csv
awk '/error/ {print}' log.txt
awk '{if ($3 > 80) print $0}' file.txt
awk '{sum+=$1} END {print sum}' file.txt
|
七、实战案例
7.1 表单验证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| const validators = { email: (value) => { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) ? '' : '请输入有效的邮箱地址'; }, phone: (value) => { return /^1[3-9]\d{9}$/.test(value) ? '' : '请输入有效的手机号'; }, password: (value) => { if (value.length < 8) return '密码至少8位'; if (!/[A-Z]/.test(value)) return '密码需包含大写字母'; if (!/[a-z]/.test(value)) return '密码需包含小写字母'; if (!/\d/.test(value)) return '密码需包含数字'; return ''; }, idCard: (value) => { return /^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/.test(value) ? '' : '请输入有效的身份证号'; } };
|
7.2 数据提取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import re
log = '2026-02-13 10:30:45 ERROR: Connection failed' time = re.search(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}', log) print(time.group())
text = 'Server IP: 192.168.1.100, Client IP: 10.0.0.1' ips = re.findall(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', text) print(ips)
json_str = '{"name": "John", "age": 30}' name = re.search(r'"name":\s*"([^"]+)"', json_str) print(name.group(1))
text = '联系电话:13812345678 或 13998765432' phones = re.findall(r'1[3-9]\d{9}', text) print(phones)
|
7.3 文本替换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import re
text = '2026/02/13, 2025-12-01, 2024.01.15' result = re.sub(r'(\d{4})[/\.](\d{2})[/\.](\d{2})', r'\1-\2-\3', text) print(result)
text = '手机号:13812345678' result = re.sub(r'(\d{3})\d{4}(\d{4})', r'\1****\2', text) print(result)
text = 'Hello World !' result = re.sub(r'\s+', ' ', text) print(result)
text = '价格:299元,原价399元' result = re.sub(r'原价(\d+)元', r'原价\1元(省\1元)', text) print(result)
|
八、速查表
8.1 元字符
| 字符 |
说明 |
. |
任意字符 |
\d |
数字 |
\D |
非数字 |
\w |
字母数字下划线 |
\W |
非字母数字下划线 |
\s |
空白字符 |
\S |
非空白字符 |
^ |
开头 |
$ |
结尾 |
8.2 量词
| 量词 |
说明 |
* |
0或多个 |
+ |
1或多个 |
? |
0或1个 |
{n} |
n个 |
{n,} |
n或多个 |
{n,m} |
n到m个 |
8.3 字符类
| 字符类 |
说明 |
[abc] |
a或b或c |
[^abc] |
非a非b非c |
[a-z] |
a到z |
[0-9] |
0到9 |
8.4 分组
| 分组 |
说明 |
(abc) |
捕获组 |
(?:abc) |
非捕获组 |
(?<name>abc) |
命名组 |
九、在线工具
参考资料
持续更新中…欢迎收藏!
#正则表达式 #Regex #字符串匹配 #教程