跳转到主内容
极星编程网:以代码为星,赴技术山海!

使用正则表达式精准提取三行头+多行正文的日志结构数据

本文介绍如何用 Python 的 re 模块(启用多行模式)设计稳健的正则表达式,从分隔符为19个等号的三行头日志中,准确捕获时间摘要标题与后续多行正文内容,并避免常见捕获组覆盖问题。 本文介绍如何用 python 的 `re` 模块(启用多行模式)设计稳健的 正则表达式 ,从分隔符为19个等号的三行头日志中,准确捕获时间摘要标题与后续多行正文内容,并避免常见捕获组覆盖问题。 在解析结构化程度较低但具有固定分隔模式的日志文件时,正则表达式仍是高效且轻量的选择。本例中,日志采用「19个等号 → 时间摘要行 → 19个等号 → 空行 → 多行正文 → 下一组分隔符」的循环结构。关键挑战在于:既要 精确界定每个记录的边界 ,又要 完整捕获跨行正文内容 ,同时避免因重复捕获组(如 (.*)+)导致仅保留最后一行的陷阱。 ✅ 推荐正则表达式(多行模式下)
import re pattern = r'^={19}\n(?!={19}$)(.+)\n={19}((?:\n(?!={19}$).*)*)' log_content = """=================== 2024-05-20 14:23:18 - User login failed =================== Invalid credentials for user 'admin'. Attempt from IP: 192.168.1.105. Session ID: sess_7a8b9c =================== 2024-05-20 14:25:02 - Database connection timeout =================== Failed to connect to primary DB (host: db-prod.internal). Retry count: 3. Last error: 'Connection refused'. """ # 启用 MULTILINE 模式:使 ^ 和 $ 匹配每行起止 matches = re.findall(pattern, log_content, re.M) for i, (header, body) in enumerate(matches, 1): print(f"Record{i}Field1:\n{header.strip()}") print(f"Record{i}Field2:\n{body.strip()}\n")
输出示例:
Record1Field1: 2024-05-20 14:23:18 - User login failed Record1Field2: Invalid credentials for user 'admin'. Attempt from IP: 192.168.1.105. Session ID: sess_7a8b9c Record2Field1: 2024-05-20 14:25:02 - Database connection timeout Record2Field2: Failed to connect to primary DB (host: db-prod.internal). Retry count: 3. Last error: 'Connection refused'.
? 表达式逐段解析 片段说明^={19}\n行首匹配 19 个 = 后跟换行(^ 在 re.M 下匹配每行开头)(?!={19}$)(.+)标题行:负向先行断言确保该行不是19 个 =,再捕获非空内容\n={19}紧接其后的第二行分隔符(换行 + 19 个 =)((?:\n(?!={19}$).*)*)正文块:非捕获组 (?:...) 重复匹配「换行 + 非分隔符行」,避免捕获组覆盖;* 可匹配零行或多行正文 ⚠️ 注意事项: perl正则表达式学习手册pdf版 perl正则表达式学习手册pdf版,点击下载解压即可。想学习perl正则的朋友需要看。 下载 必须传入 re.M(re.MULTILINE)标志,否则 ^/$ 仅匹配全文首尾; 不推荐使用 .* 贪婪匹配正文(如原尝试中的 (\n.*)+),它会吞掉后续分隔符并导致边界错位; 若正文可能为空,可将末尾 * 改为 *?(惰性)或额外处理空值逻辑; 实际生产中建议配合 re.compile() 预编译提升性能,并添加 re.DOTALL(若需匹配含换行的单字段)——但本例中已通过显式 \n 控制更安全。 ✅ 后续处理建议 提取出 (header, body) 元组后,可轻松映射为结构化数据:
records = [ {"timestamp_summary": h.split(" - ", 1)[0].strip(), "summary": h.split(" - ", 1)[1].strip() if " - " in h else "", "content": b.strip()} for h, b in matches ] # 直接写入 SQLite / Pandas DataFrame / JSONL 文件等
该方案兼顾准确性、可读性与可维护性,适用于日志预处理、ETL 清洗及轻量级数据库导入场景。

相关文章