Sublime Text 提取目录依赖正则匹配人工标题,需用^#{1,6}\s+1+(?=\s*$)精准匹配Markdown标题,HTML标题需另写正则,Find All后需锚定^和$才能Ctrl+L选整行,跨文件提取需手动清理、去重、排序及缩进处理。#\n\r ↩

Sublime Text 无法自动识别 Markdown 或 HTML 的语义标题结构,所谓“提取目录”,本质是用正则匹配人工编写的标题行(如 # 标题、## 子标题),再手动整理层级。别指望它生成带跳转链接的 TOC,那是预处理器或插件的事。
怎么写正则精准匹配 Markdown 标题行
Markdown 标题必须以 # 开头、后跟空格、再接文字,且不能有其他字符干扰(比如注释或内联代码)。直接搜 #.* 会误吞整行甚至跨行,必须锚定边界。
- 正确写法:
^#{1,6}\s+[^#\n\r]+(?=\s*$)——^锁行首,{1,6}限定最多六级,\s+强制至少一个空白,[^#\n\r]+排除后续#和换行,(?=\s*$)确保后面只有空白或到行尾 - 常见失效原因:没点
.*图标启用正则;#没转义(其实不用,但写成\#也没错);.默认不匹配换行,所以.*不会越界,反而是优点 - 如果文档混有 HTML 标题(如
<h2>xxx</h2>),得另写一条:^<h[1-6][^>]*>[^<]+</h[1-6]>$,并确保. matches newline关闭(否则可能跨标签匹配)
为什么 Find All 后 Ctrl+L 没选中整行
因为正则没显式包含行首 ^ 和行尾 $,Find All 只高亮匹配片段本身(比如只框住 ## API 这几个字符),光标停在开头,不是整行。这时按 Ctrl+L 无效——它只对“已选中整行起始位置”的光标生效。
- 必须用
^##\s+.*$这类带锚点的写法,Find All才会让光标落在每行开头 - 确认方法:
Find All后看状态栏是否显示“X occurrences selected”且光标呈竖线状分布在各行首;若显示“X matches found”但无选中,则说明没锚定 - Mac 用户注意:
Cmd+L是快捷键,不是Ctrl+L;系统键盘映射冲突时,优先以菜单栏Selection → Expand Selection to Line为准
跨文件提取所有标题并去重排序
单文件够用,但项目里多个 .md 文件的标题要聚合,就得靠 Find in Files(Ctrl+Shift+F),但它输出带路径前缀,且不支持去重——这两步必须手动补。
- Where 栏填:
**/*.md(安全)或docs/,README.md(精确),绝不能留空或填* - 搜索框填同上的标题正则,勾选
Regular Expression(右下角.*必须蓝) - 搜索完成后,结果页全选(
Ctrl+A)→ 复制 → 新建窗口粘贴,内容形如:api.md:12:### Request Body - 清理前缀:用
Ctrl+H,查找^[^:]+:\d+:,替换为空(注意开启正则);再删空行:^[ \t]*$ - 去重排序:选中全部文本 →
Ctrl+Shift+P→ 输入Sort Lines→ 回车;重复执行一次Remove Duplicate Lines(需提前安装 Package Control 的相应插件,原生不支持)
提取后缩进层级对不齐?问题出在空格和制表符
正则能抓出 # 数量,但 Sublime 不提供“按 # 个数自动缩进”的功能。你复制出来的纯文本列表默认是平铺的,要体现层级,得靠后续替换或列编辑。
- 简单方案:先用
Ctrl+H替换^#{6}\s+→(6 个空格),^#{5}\s+→……逐级替换;注意^必须保留,否则会全局替换所有##### - 风险点:
\s+包含 Tab,若原文档混用空格和 Tab,替换后缩进可能错乱;建议先统一用View → Indentation → Convert Indentation to Spaces - 真正难处理的是带链接的标题,如
## [Intro](#intro)——正则很难干净剥离括号和 URL,此时不如放弃自动提取,改用 Pandoc 或markdown-tocCLI 工具生成标准 TOC
最常被忽略的其实是原始格式约束:正则只认字符串模式,不管语义。如果标题里有反斜杠转义(\# Not a heading)、代码块内误判、或 YAML front matter 里的 #,它都会照单全收。这种时候,宁可少提几条,也别开 . matches newline 硬刚——越界匹配的代价远高于手动补漏。

















