阿P的江湖密令:正则表达式通关秘籍
前情提要:阿P晋升版本控制长老后,突遇紧急任务——处理十万条江湖人士登记信息!面对杂乱无章的"姓名:张无忌|年龄:25|门派:明教"数据,阿P抓狂:"这要提取到猴年马月?"扫地僧师傅神秘一笑:"该学正则了!"
第一章:初识江湖密令
场景:数据提取的绝望
阿P盯着密密麻麻的登记簿:
姓名:张无忌|年龄:25|门派:明教
姓名:赵敏,年龄:18,门派:朝廷
名:周芷若 岁数:20 所属:峨眉
师傅掏出一张泛黄羊皮卷:"此乃正则表达式,江湖数据处理的无上密令!"
核心概念:
正则 = 万能匹配公式
\d
= 数字 (d=digit)
\w
= 字母/数字/下划线 (w=word)
.
= 任意单个字符
+
= 出现1次或多次
*
= 出现0次或多次
第二章:基础匹配心法
场景:提取所有姓名
师傅在羊皮卷书写:
import re
# 原始数据
data = "姓名:张无忌|年龄:25|门派:明教"
# 基础匹配:匹配"姓名:"后的中文字符
pattern = r"姓名:(\w+)" # \w+ 匹配连续汉字/字母
match = re.search(pattern, data)
if match:
print(match.group(1)) # 输出:张无忌
实战升级:处理多格式
# 通配符 .*? 匹配任意字符(非贪婪模式)
pattern = r"名[称:: ]*(\w+)"
# 匹配:名(称::空格等) + 中文名
texts = [
"姓名:张无忌",
"名:赵敏",
"名称:周芷若"
]
for text in texts:
match = re.search(pattern, text)
print(match.group(1) if match else "未匹配")
# 输出:
# 张无忌
# 赵敏
# 周芷若
第三章:高级捕获术
场景:同时提取三项信息
面对复杂数据:
张无忌,25岁,明教教主
赵敏-18-郡主
周芷若 20 峨眉掌门
师傅画出神秘符咒:
pattern = r"(\w+)[, -]+(\d+)岁?[, -]+(\w+.*)"
# 分解:
# 1. (\w+) 捕获姓名
# 2. [, -]+ 分隔符(,或-或空格)
# 3. (\d+)岁? 捕获年龄("岁"可有可无)
# 4. [, -]+ 分隔符
# 5. (\w+.*) 捕获门派和职务
data = "张无忌,25岁,明教教主"
match = re.match(pattern, data)
if match:
name, age, sect = match.groups()
print(f"姓名:{name} 年龄:{age} 门派:{sect}")
# 输出:姓名:张无忌 年龄:25 门派:明教教主
第四章:江湖验证大阵
场景:用户输入校验
阿P开发注册系统需验证:
用户名:3-10位字母/数字/中文
密码:8-20位,含大小写+数字
手机号:11位数字
邮箱:标准格式
师傅布下正则结界:
def validate_username(username):
"""用户名:中英文/数字,3-10字符"""
return bool(re.match(r"^[\u4e00-\u9fa5\w]{3,10}$", username))
def validate_password(password):
"""密码:8-20位,含大小写和数字"""
return bool(re.match(r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,20}$", password))
def validate_phone(phone):
"""手机号:11位数字"""
return bool(re.match(r"^1[3-9]\d{9}$", phone))
def validate_email(email):
"""邮箱:标准格式"""
return bool(re.match(r"^[\w.-]+@[a-zA-Z\d-]+(\.[a-zA-Z\d-]+)*\.[a-zA-Z]{2,}$", email))
# 测试
print(validate_username("张无忌_123")) # True
print(validate_password("Abcd1234")) # True
print(validate_phone("13800138000")) # True
print(validate_email("zhangwuji@mingjiao.org")) # True
第五章:文本替换神功
场景:敏感信息脱敏
老板要求:
手机号中间4位变星号
身份证保留首尾,中间变星号
银行卡保留后4位
师傅演示替换大法:
def censor_text(text):
# 手机号脱敏:138****8000
text = re.sub(r"(\d{3})\d{4}(\d{4})", r"\1****\2", text)
# 身份证脱敏:1101**********123X
text = re.sub(r"(\d{4})\d{10}(\w{4})", r"\1**********\2", text)
# 银行卡脱敏:**** **** **** 1234
text = re.sub(r"\d{4}(\d{8})(\d{4})", r"**** **** **** \2", text)
return text
original = """
用户资料:
手机:13800138000
身份证:11010519950101123X
银行卡:6225880123456789
"""
print(censor_text(original))
# 输出:
"""
用户资料:
手机:138****8000
身份证:1101**********123X
银行卡:**** **** **** 6789
"""
第六章:实战:秘籍解析
场景:解析武功秘籍
秘籍格式:
[九阳神功]
作者:达摩祖师
招式:氤氲紫气|缩骨功|龟息功|壁虎游墙
心法:他强由他强...(共200字)
[乾坤大挪移]
作者:山中老人
招式:移宫换穴|...(省略)
阿P需要提取:
武功名称
作者
招式数量
师傅挥毫写符:
secret_text = """
[九阳神功]
作者:达摩祖师
招式:氤氲紫气|缩骨功|龟息功|壁虎游墙
心法:他强由他强...(共200字)
[乾坤大挪移]
作者:山中老人
招式:移宫换穴|借力打力|隔空取物
"""
# 多级匹配
pattern = r"\[(\w+)\].*?作者:(\w+).*?招式:([^\n]+)"
matches = re.findall(pattern, secret_text, re.DOTALL)
for name, author, moves in matches:
move_count = len(moves.split("|"))
print(f"武功:{name} 作者:{author} 招式数:{move_count}")
# 输出:
# 武功:九阳神功 作者:达摩祖师 招式数:4
# 武功:乾坤大挪移 作者:山中老人 招式数:3
第七章:避坑指南
常见陷阱与解法:
贪婪吞噬:默认
.*
会匹配到行尾 解法:用非贪婪.*?
# 错误:匹配整个字符串
re.search(r"「.*」", "「九阴」真经「九阳」神功")
# 正确:匹配首个
re.search(r"「.*?」", "「九阴」真经「九阳」神功").group() # 「九阴」
2.特殊字符:.
*
+
等需转义
# 错误:匹配任何字符+plus
re.search(r".+", "1+1=2")
# 正确:匹配真正的加号
re.search(r"\d+\+\d+", "1+1=2").group() # 1+1
3.回溯灾难:复杂表达式导致卡死
解法:避免嵌套
(.*)*
,用具体字符集
# 危险表达式(可能卡死)
r"((a*)*)*b"
# 安全替代
r"[ab]*b"
终章:正则宗师的诞生
三月后,光明顶数据大会。各大门派展示数据处理能力:
少林派:500僧人手工整理,耗时10日
武当派:30弟子编写脚本,耗时3日
朝廷:重金购买西域软件,耗银万两
轮到阿P时,只见他轻敲键盘:
import re
def process_data(raw):
# 单行正则解决战斗
pattern = r"(.+?)[::](\w+)[,,]?年龄[::](\d+)[,,]?门派[::](\w+)"
return re.findall(pattern, raw)
raw_data = "姓名:张无忌,年龄:25,门派:明教;名:赵敏 年龄:18 门派:朝廷..."
result = process_data(raw_data)
十万数据,弹指间处理完毕!全场震惊!
扫地僧师傅欣慰道:"正则七重境你已掌握:
基础匹配(
\d \w .
)次数控制(
+ * ? {}
)字符集合(
[a-z] [^0-9]
)分组捕获(
( )
)首尾定位(
^ $
)替换妙用(
re.sub
)模式开关(
re.I re.M
)
记住:正则非万能,清晰胜巧妙!"
从此,江湖人称阿P——"正则圣手"!