欢迎光临
我们一直在努力

用正则表达式批量处理 Markdown 文件:替换、提取、校验(附 Python 脚本实战)

在维护大型文档项目(如技术手册、博客仓库、知识库)时,你是否曾遇到以下痛点?

  • 需要将所有 ![alt](old_path) 图片链接批量替换为新 CDN 地址;
  • 想从上百篇 .md 文件中提取所有标题,生成目录索引;
  • 团队提交的 Markdown 存在格式不规范(如空行缺失、标题未对齐),需自动校验。

手动逐个修改?效率低下且易出错!

本文将教你如何利用 正则表达式(Regex) + Python 脚本,高效完成 Markdown 文件的批量替换、内容提取与格式校验,并提供可直接运行的代码模板,助你实现“一键自动化”!


一、为什么选择正则表达式处理 Markdown?

虽然 Markdown 是结构化文本,但其语法简单、规则明确,非常适合用正则进行模式匹配。相比解析 AST(如使用 markdown-it),正则方案具有:

  • 轻量快速:无需依赖重型解析库;
  • 灵活可控:精准定位特定模式;
  • 易于集成:一行命令或脚本即可执行。

注意:正则不适合处理嵌套结构(如表格内含代码块),但对于 90% 的日常任务(链接、图片、标题、代码块等)完全够用。


二、常用 Markdown 元素正则模式速查表

元素正则表达式说明
一级标题 ^# (.+)$ 匹配 # 标题
二级标题 ^## (.+)$ 匹配 ## 子标题
图片 !$$([^$$]*)$$$([^)]+)$ 提取 alt 和 url
超链接 $$(.+?)$$$(https?://[^)]+)$ 匹配外部链接
行内代码 `([^`]+)` 匹配 `code`
代码块 (\\w+)?\\n([\\s\\S]*?)\\n 匹配带语言标识的代码块
无序列表 ^[-*+] (.+)$ 匹配 – item
任务列表 ^- $$([ x])$$ (.+)$ 提取状态与内容

小技巧:在 regex101.com 上测试你的正则,选择 Python Flavor。


三、实战场景 1:批量替换图片链接(迁移 CDN)

需求

将所有本地图片路径 ./images/xxx.png 替换为 CDN 地址 2026-02-1320ith0etzle.png。

正则思路

  • 匹配图片 URL 中包含 ./images/ 的部分;
  • 保留文件名,替换前缀。

Python 脚本

import re
import os
import glob

def replace_image_links(md_file, old_prefix="./images/", new_prefix="https://cdn.example.com/blog/"):
with open(md_file, 'r', encoding='utf-8') as f:
content = f.read()

# 正则:匹配图片URL中old_prefix开头的部分
pattern = r'!$$([^$$]*)$$$' + re.escape(old_prefix) + r'([^)]+)$'
repl = r'![\\1](' + new_prefix + r'\\2)'

new_content = re.sub(pattern, repl, content)

with open(md_file, 'w', encoding='utf-8') as f:
f.write(new_content)

# 批量处理所有 .md 文件
for md_file in glob.glob("docs/**/*.md", recursive=True):
replace_image_links(md_file)
print(f"已处理: {md_file}")

关键点:

  • 使用 re.escape() 避免特殊字符干扰;
  • \\1, \\2 引用捕获组,保留 alt 文本和文件名。

四、实战场景 2:提取所有标题生成目录

需求

扫描整个项目,提取所有 #、##、### 标题,输出层级化目录。

Python 脚本

import re
import glob

def extract_headings(md_file):
with open(md_file, 'r', encoding='utf-8') as f:
lines = f.readlines()

headings = []
for line in lines:
if line.startswith('#'):
level = line.count('#')
title = line.strip('# \\n')
headings.append((level, title))
return headings

all_headings = []
for md_file in glob.glob("posts/*.md"):
headings = extract_headings(md_file)
all_headings.extend(headings)

# 输出 Markdown 目录
for level, title in all_headings:
indent = " " * (level 1)
print(f"{indent}– [{title}](#{title.lower().replace(' ', '-')})")

输出示例:

– [入门指南](#入门指南)
– [安装步骤](#安装步骤)
– [基本配置](#基本配置)
– [高级用法](#高级用法)


五、实战场景 3:校验 Markdown 格式规范

常见规范要求

  • 标题前后必须有空行;
  • 图片必须包含非空 alt 文本;
  • 不允许连续两个以上空行。

校验脚本(部分)

import re

def validate_markdown(md_file):
with open(md_file, 'r', encoding='utf-8') as f:
content = f.read()
lines = content.split('\\n')

errors = []

# 规则1: 标题前后需空行
for i, line in enumerate(lines):
if line.startswith('#'):
if i > 0 and lines[i1].strip() != '':
errors.append(f"L{i+1}: 标题前缺少空行")
if i < len(lines)1 and lines[i+1].strip() != '':
errors.append(f"L{i+1}: 标题后缺少空行")

# 规则2: 图片 alt 文本不能为空
empty_alt = re.findall(r'!$$$$$[^)]+$', content)
if empty_alt:
errors.append("存在空 alt 文本的图片")

# 规则3: 禁止连续3个以上空行
if re.search(r'\\n\\s*\\n\\s*\\n\\s*\\n', content):
errors.append("存在连续3个以上空行")

return errors

# 执行校验
for md_file in glob.glob("*.md"):
errs = validate_markdown(md_file)
if errs:
print(f" {md_file} 发现问题:")
for e in errs:
print(f" – {e}")

可集成到 CI 流程,在 Git 提交前自动检查。


六、高级技巧:处理多行模式与贪婪匹配

问题:代码块跨多行,如何精准匹配?

# 正确写法:使用 [\\s\\S] 匹配任意字符(包括换行)
code_block_pattern = r'```(\\w+)?\\n([\\s\\S]*?)\\n```'

问题:避免过度匹配(如多个图片连在一起)

  • 使用非贪婪匹配 .*? 而非 .*
  • 示例:$$(.*?)$$$(.*?)$ 而不是 $$(.*)$$$(.*)$

七、工具推荐:无需编程也能用正则

  • VS Code: Ctrl+Shift+H 全局搜索替换,支持正则(勾选 .* 图标)
  • Notepad++: 查找 → 替换 → 勾选“正则表达式”
  • 在线工具: RegExr、Text Mechanic

总结:正则 + Markdown = 自动化利器

任务类型推荐方案
简单替换 VS Code 正则替换
批量处理 Python 脚本 + glob
格式校验 自定义规则 + CI 集成
复杂结构 结合 markdown 库解析 AST

记住:不要试图用正则解析所有 Markdown,但 80% 的重复劳动,它都能帮你干掉!


赞(0)
未经允许不得转载:171主机测评 » 用正则表达式批量处理 Markdown 文件:替换、提取、校验(附 Python 脚本实战)
分享到: 更多 (0)

评论 抢沙发

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