欢迎光临
我们一直在努力

正则表达式实战:10 个高频场景 + 调试方法,一次讲透

正则表达式实战:10 个高频场景 + 调试方法,一次讲透

正则不是背出来的,是练出来、调出来的。

刚学编程时我以为正则是"魔法符号",后来发现它就是一套清晰规则。这篇先给一张速查表,再带你用 10 个真实场景把规则用熟,最后讲怎么调试、怎么避开性能大坑。


一、速查表

元字符

符号含义
. 任意单字符(除换行)
\\d \\w \\s 数字 / 词字符 / 空白
\\D \\W \\S 对应取反
^ $ 行首 / 行尾

量词:*(0+)、+(1+)、?(0 或 1)、{n,m}(n 到 m 次)。

分组与断言:( ) 捕获组、(?: ) 非捕获、(?=x) 后面是 x、(?!x) 后面不是 x。

标志位:i 忽略大小写、g 全局、m 多行、s 让 . 匹配换行。


二、10 个高频场景

1. 邮箱格式校验(不要过度精确)

import re
pattern = r"^[\\w.+-]+@[\\w-]+\\.[\\w.-]+$"
print(bool(re.match(pattern, "a.b+c@sub.example.com"))) # True

解释:\\w.+- 覆盖用户名常见字符,@ 后匹配域名和点。别追求 100% 符合 RFC,能挡住明显错误就行。

2. 手机号(含 +86 与分隔符容错)

pattern = r"^[+]?86[-\\s]?1[3-9]\\d{9}$"
print(bool(re.match(pattern, "+86 13812345678"))) # True

[+]? 可选加号,[-\\s]? 容忍空格或横杠,核心 11 位以 1[3-9] 开头。

3. 强密码校验(用 lookahead)

pattern = r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[^A-Za-z0-9]).{8,}$"
print(bool(re.match(pattern, "Abcd123!"))) # True

四个 (?=.*x) 正向断言分别要求有小写、大写、数字、符号,末尾 .{8,} 限长度。

4. 提取 URL 的域名与路径参数

pattern = r"https?://([^/]+)(/[^?]*)?(\\?.*)?"
m = re.match(pattern, "https://shop.com/list?page=2")
print(m.group(1), m.group(2)) # shop.com /list

三组捕获分别拿域名、路径、查询串。

5. 中文匹配

# 匹配中文字符范围
pattern = r"[\\u4e00-\\u9fa5]+"
text = "张三 zhangsan 李四"
print(re.findall(pattern, text)) # ['张三', '李四']

# 去除所有中文
print(re.sub(r"[\\u4e00-\\u9fa5]", "", text)) # ' zhangsan '

6. 金额千分位(捕获组 + 反向引用思路)

# 每三位数字前加逗号(从右往左)
text = "1234567"
print(re.sub(r"(?<=\\d)(?=(\\d{3})+(?!\\d))", ",", text)) # 1,234,567

用先行断言找"后面是 3 的倍数个数字且不是数字结尾"的位置插入逗号。

7. HTML 标签匹配与去除

html = "<p>hello <b>world</b></p>"
print(re.sub(r"<[^>]+>", "", html)) # hello world

提醒:这只是应急。完整 HTML 嵌套复杂,正则无法正确处理,正式场景请用解析库(如 Python 的 BeautifulSoup、JS 的 DOMParser)。

8. 日志时间戳批量替换(re.sub 带函数)

import re
log = " [2023-01-01] ok\\n [2024-05-20] fail\\n"
# 把日期统一改成标记
print(re.sub(r"\\[(\\d{4}-\\d{2}-\\d{2})\\]", lambda m: "[OLD]", log))

sub 的第二参数传函数,可对每个匹配做任意转换。

9. 重复词检测

pattern = r"\\b(\\w+)\\s+\\1\\b"
text = "the the cat sat"
print(re.findall(pattern, text)) # ['the']

\\1 反向引用第一个捕获组,配 \\b 词边界避免误判。

10. 敏感词过滤(大小写不敏感 + 词边界)

words = ["苹果", "香蕉"]
text = "我爱吃苹果,也买过苹果派,山东的苹果不错"
# 用前后词边界保证整词匹配,避免子串误伤
pattern = r"(?<!\\w)" + "|".join(words) + r"(?!\\w)"
print(re.sub(pattern, "***", text, flags=re.IGNORECASE))

前后 (?<!\\w)(?!\\w) 保证整词匹配,避免把"苹果派"里的"苹果"单独替换或子串误伤。


三、调试方法

  • regex101.com:在线高亮匹配、逐字符解释,我首选。
  • grep -E:命令行快速验证grep -E "^[a-z]+@[a-z]+\\." emails.txt
  • Python re.DEBUG:打印正则的解析树,看哪里写错:re.compile(r"\\d+", re.DEBUG)

贪婪 vs 非贪婪:.* 贪婪会一直吃到最后,.*? 非贪婪遇到第一个满足条件的就停。替换 HTML 标签一定要用 <.+?> 而非 <.+>。

灾难性回溯:像 (a+)+$ 配长串 aaaa….X 会让引擎指数级爆炸。避免嵌套量词,必要时用原子组或改写表达式。

什么时候别用正则:简单分割、固定前缀判断、大小写替换,直接用字符串方法(split、startswith、replace)更快更稳,别什么都上正则。


我建议你把上面 10 段代码逐条复制到一个 test_regex.py 里跑一遍,改改输入看匹配怎么变——真正写熟正则,靠的是亲手调,不是背表。

赞(0)
未经允许不得转载:171主机测评 » 正则表达式实战:10 个高频场景 + 调试方法,一次讲透
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址