大家好,我是你们的老朋友。今天咱们来聊一聊一个既让人头大、又让人兴奋的东西------正则表达式。
如果你刚开始接触它,大概率会觉得:"这玩意儿看着像一串加密过的咒语,鬼才看得懂!" 但等你真的学会之后,你会忍不住感叹:正则表达式就是文本处理的瑞士军刀。
想象一下,你需要:
- 验证手机号是不是 11 位数字?
- 批量提取日志里的 IP 地址?
- 清洗掉用户输入中奇怪的符号?
如果没有正则,你可能要写一堆 if-else,还得一个一个循环。 但有了正则,三两行代码就能搞定。
所以今天这一篇,我打算带你从最基础的概念到各种常见用法,把正则的精髓讲透。保证你看完就能上手,工作中直接用。

一、正则到底是个啥?
用一句话概括:正则就是一套专门用于字符串匹配的规则语言。
你可以把它理解为"用一套符号写下来的过滤规则",Python 自带的 re
模块就是这把钥匙。
python
import re # Python的正则表达式模块
# 简单示例:检查字符串是否以h开头
result = re.match('h', 'hello')
print(result) # 匹配成功,返回Match对象
很多人第一次看到正则时,心里的想法是: "这点小事,写个 if 不香吗?"
没错,小场景确实没必要用正则。但当规则一复杂,if else 马上变成灾难,维护起来比天书还难。
而正则写起来可能就一行:又短、又快、又精准。
二、五大常用匹配方法
先别急着背各种符号,咱们先搞清楚 re
里最常见的五种操作。
re.match()
:从头匹配
ini
result = re.match('h','hello') # 成功
print(result.group()) # 输出: h
result = re.match('h','world') # 失败
print(result) # None
re.search()
:全局找第一个
bash
re.search('h','hello world') # 找到第一个 h
re.search('h','world hello') # 找到中间的 h
re.findall()
:找全部
scss
results = re.findall('h','hello world hi')
print(results) # ['h', 'h']
re.finditer()
:找全部(迭代器版)
python
matches = re.finditer(r'\d+','共有3个苹果和5个橙子')
for match in matches:
print(f"找到数字: {match.group()},位置: {match.span()}")
输出:
makefile
找到数字: 3,位置: (2, 3)
找到数字: 5,位置: (8, 9)
re.sub()
:替换
python
text = "今天是2023-12-15,明天是2023-12-16"
new_text = re.sub(r'\d{4}-\d{2}-\d{2}','XXXX-XX-XX', text)
print(new_text)
# 输出: 今天是XXXX-XX-XX,明天是XXXX-XX-XX
这五个函数,基本覆盖了 80% 的正则应用场景。
三、字符匹配规则(别硬背,用场景记)
正则里最让人头疼的就是各种符号。我的建议是------别死记硬背,最好和实际场景绑定着记。
1. 单字符匹配
python
# . 匹配任意字符(除换行符)
re.match('.','a') # 匹配
re.match('.','1') # 匹配
re.match('.','\n') # 不匹配
# [] 匹配集合
re.match('[abc]','a') # 匹配 a/b/c
re.match('[a-z]','m') # 匹配任意小写字母
re.match('[0-9]','5') # 匹配数字
2. 预定义类(速记法)
python
# \d 匹配数字
re.match(r'\d','123') # 匹配1
# \D 非数字
re.match(r'\D','abc') # 匹配a
# \s 空格、制表符等
re.match(r'\s',' hello') # 匹配空格
# \w 字母数字下划线
re.match(r'\w','hello') # 匹配h
这些符号一旦熟练,写正则就像写公式一样顺手。
四、数量规则:出现几次?
1. 常见符号
python
# * 0次或多次
re.match(r'a*','aaa') # 匹配aaa
re.match(r'a*','') # 匹配空
# + 1次或多次
re.match(r'a+','aaa') # 匹配aaa
re.match(r'a+','') # 不匹配
# ? 0次或1次
re.match(r'a?','a') # 匹配a
re.match(r'a?','') # 匹配空
2. 精确次数
python
re.match(r'a{3}','aaa') # 精确3次
re.match(r'a{2,}','aaa') # 至少2次
re.match(r'a{2,4}','aaa') # 2到4次
这几个符号加上前面的字符类,就能拼出大多数日常需求。
五、位置规则:锚点在哪里?
有时候我们不只关心"是什么",还要关心"在哪里"。
python
# ^ 匹配开头
re.match('^h','hello') # 匹配
# $ 匹配结尾
re.search('d$','world') # 匹配
# \b 单词边界
re.search(r'\bword\b','hello word test') # 匹配
还有分组和或:
python
# | 或匹配
re.match('a|b','a') # 匹配a
re.match('a|b','b') # 匹配b
# () 分组捕获
result = re.match(r'(\w+)-(\d+)','order-12345')
print(result.group(1)) # order
print(result.group(2)) # 12345
六、贪婪与非贪婪:能少就少
正则的一个坑就是"贪婪模式"。默认情况下,.*
会吃掉尽可能多的字符。
ini
text ='学习python课程,学习Java课程'
result = re.search('学习.*课程', text)
print(result.group()) # 学习python课程,学习Java课程
加个 ?
就变成非贪婪:
ini
result = re.search('学习.*?课程', text)
print(result.group()) # 学习python课程
很多新手正则写错,90% 是因为忘记非贪婪。
七、几个超实用案例
1. 提取 URL
python
def extract_urls(text):
pattern = r'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+[/\w.-]*'
return re.findall(pattern, text)
text = '访问官网 https://www.example.com 或 http://test-site.org/path'
urls = extract_urls(text)
print(urls)
# ['https://www.example.com', 'http://test-site.org/path']
2. 提取中文
python
text ='Hello世界!Python编程很有趣。123数字'
chinese_chars = re.findall(r'[\u4e00-\u9fff]+', text)
print(chinese_chars) # ['世界', '编程很有趣']
3. 数据清洗
python
def clean_data(text):
text = re.sub(r'\s+',' ', text) # 去掉多余空格
text = re.sub(r'[^\w\u4e00-\u9fff\s.,!\?]','', text) # 去掉杂符号
return text.strip()
dirty_text = ' Hello 世界!@#¥% Python编程... '
clean_text = clean_data(dirty_text)
print(clean_text) # 'Hello 世界! Python编程...'
八、高级技巧
1. 命名分组
python
text ="姓名: 张三, 年龄: 25, 城市: 北京"
pattern = r"姓名: (?P<name>\w+), 年龄: (?P<age>\d+), 城市: (?P<city>\w+)"
match= re.search(pattern, text)
if match:
print(f"姓名: {match.group('name')}")
print(f"年龄: {match.group('age')}")
print(f"城市: {match.group('city')}")
2. 提前编译
python
pattern = re.compile(r'\b\w{4,}\b')
text = "正则表达式是一个非常强大的文本处理工具"
long_words = pattern.findall(text)
print(long_words)
# ['正则表达式', '非常', '强大', '文本处理', '工具']
九、写正则要注意啥?
- 加
r
:用原始字符串避免转义 - 多复用 :常用的正则建议
compile
提前编译 - 小心 None:匹配不到要判断
- 别太复杂:可读性第一,必要时加注释
ini
pattern = re.compile(r"""
^ # 开头
(\w+) # 用户名
@ # @符号
([a-zA-Z0-9.-]+) # 域名
. # 点号
([a-zA-Z]{2,4}) # 顶级域名
$ # 结束
""", re.VERBOSE)
十、最后的碎碎念
学正则最重要的一点:一定要多写,多试。
刚开始你可能觉得像看天书,但等到有一天你能写出一个三行的正则,解决了别人三十行的代码,那种快感简直爆棚。
正则表达式就像是键盘侠的秘密武器,谁掌握了,谁在数据处理的世界里就多了一份底气。
所以,别怕复杂,从最简单的 \d
和 \w
开始,慢慢往上堆。相信我,用不了多久,你就能和正则成为"并肩作战的老伙计"。