订阅更新

正则表达式解析日志比split快5倍——Python文本处理

Python手册 第 14 题 约 3 分钟读完

本文目录
  1. 先说结论
  2. 正则基础
  3. compile预编译性能
  4. 贪婪vs非贪婪
  5. Pandas内置正则
  6. 实战:日志解析split vs 正则
  7. 面试高频追问
  8. 总结

先说结论

大数据文本处理核心正则技巧:① 命名分组(?P)提取字段;② re.compile()预编译;③ 贪婪vs非贪婪控制范围。简单提取用split,复杂模式用正则。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

正则基础

import re
# 命名分组提取Nginx日志
LOG_RE = re.compile(
    r'(?P<ip>\S+) \S+ \S+ '
    r'\[(?P<time>[^\]]+)\] '
    r'"(?P<method>\w+) (?P<path>\S+) \S+" '
    r'(?P<status>\d+) (?P<size>\d+)')
 
match = LOG_RE.match(log_line)
if match: data = match.groupdict()
# {'ip':'192.168.1.1','status':'200',...}

compile预编译性能

# 不预编译:100万行约1.5秒
for line in lines: re.match(r'\d{4}-\d{2}-\d{2}', line)
 
# 预编译:100万行约0.8秒(快一倍)
pat = re.compile(r'\d{4}-\d{2}-\d{2}')
for line in lines: pat.match(line)

贪婪vs非贪婪

text = '<div>hello</div><div>world</div>'
re.findall(r'<div>(.*)</div>', text)   # ['hello</div><div>world'] 贪婪
re.findall(r'<div>(.*?)</div>', text)  # ['hello','world'] 非贪婪

Pandas内置正则

df['date'] = df['log'].str.extract(r'(\d{4}-\d{2}-\d{2})')
errors = df[df['msg'].str.contains(r'ERROR|FATAL', na=False)]
df['phone'] = df['phone'].str.replace(r'(\d{3})\d{4}(\d{4})',r'\1****\2')

实战:日志解析split vs 正则

100万行Nginx日志:split方式2.5秒且格式异常崩溃;正则方式0.5秒(快5倍)且异常返回None不崩。

面试高频追问

追问一:正则灾难性回溯?

嵌套量词.*.*可能指数级回溯。用非贪婪.*?或精确字符类[^"]*替代。

追问二:match和search区别?

match从开头匹配,search在整个字符串搜索。大部分场景用search更灵活。

追问三:什么时候不该用正则?

简单split能搞定时不用。解析JSON/XML/HTML用json.loads()/lxml。正则适合半结构化文本。

总结

正则讲三层:① 核心语法(命名分组、贪婪vs非贪婪);② 性能优化(compile预编译);③ 大数据应用(日志解析比split快5倍、Pandas str.extract/contains内置正则)。

下一篇聊Python异常处理:try-except写得太粗的危害。

你们用正则做什么文本处理?评论区聊聊~

关注「Wood聊大数据」| 9年大数据老兵,只讲大数据面试干货

刷题进度保存在当前浏览器