如何使用sed将Markdown文件中的图片绝对链接转换为相对链接
实现方案
sed 实现
基于你给出的前提假设和实现步骤,可直接用如下sed命令完成替换:
单文件测试(不修改原文件,仅输出修改后的内容)
GNU sed(Linux/WSL环境):
sed 's/\(!\[.*\]\()\).*\/\([^\/]*\/[^\/]*\)\()\)/\1\3\4/' 目标文件.md
macOS 环境:
sed 's/\(!\[.*\]\()\).*\/\([^\/]*\/[^\/]*\)\()\)/\1\3\4/' 目标文件.md
直接修改单文件
GNU sed:
sed -i 's/\(!\[.*\]\()\).*\/\([^\/]*\/[^\/]*\)\()\)/\1\3\4/' 目标文件.md
macOS 环境:
sed -i '' 's/\(!\[.*\]\()\).*\/\([^\/]*\/[^\/]*\)\()\)/\1\3\4/' 目标文件.md
批量处理
处理当前目录所有.md文件:
# GNU sed sed -i 's/\(!\[.*\]\()\).*\/\([^\/]*\/[^\/]*\)\()\)/\1\3\4/' *.md # macOS sed -i '' 's/\(!\[.*\]\()\).*\/\([^\/]*\/[^\/]*\)\()\)/\1\3\4/' *.md
递归处理所有子目录的.md文件:
# GNU sed find . -name "*.md" -exec sed -i 's/\(!\[.*\]\()\).*\/\([^\/]*\/[^\/]*\)\()\)/\1\3\4/' {} +
更优实现方案(Python)
如果需要更高的兼容性、避免不同平台sed语法差异、支持非行首的图片链接,更推荐用Python脚本实现:
import re import os # 匹配标准Markdown图片语法 img_pattern = re.compile(r'(!\[.*?\]\()(.*?)(\))') def replace_img_link(match_obj): prefix = match_obj.group(1) origin_url = match_obj.group(2) suffix = match_obj.group(3) # 拆分路径取最后两段 path_parts = origin_url.rstrip('/').split('/') if len(path_parts) >= 2: new_url = '/'.join(path_parts[-2:]) return f"{prefix}{new_url}{suffix}" # 不符合路径规则的不修改 return match_obj.group(0) if __name__ == '__main__': # 递归遍历当前目录所有md文件 for root, _, files in os.walk('.'): for f_name in files: if f_name.endswith('.md'): f_path = os.path.join(root, f_name) with open(f_path, 'r', encoding='utf-8') as f: content = f.read() new_content = img_pattern.sub(replace_img_link, content) with open(f_path, 'w', encoding='utf-8') as f: f.write(new_content)
该方案优势:
- 跨平台通用,不需要区分GNU sed和BSD sed语法
- 支持嵌入在列表、引用块、段落中任意位置的图片链接,不需要强制图片标签在行首
- 可灵活扩展校验逻辑,比如仅当最后一级目录为
images时才替换,避免误改其他链接
注意事项
- 所有操作前请提前备份全部Markdown文件,避免正则误改导致内容丢失
- 如果图片链接中包含括号,需要调整正则的匹配规则避免匹配截断
内容的提问来源于stack exchange,提问作者T Wellick
相关产品推荐
相关产品推荐

