概述
Markdown 很适合于技术写作,因为技术写作并不需要花哨的排版和内容, 只要内容生动而严谨,文笔朴实而优美。
为了编写对读者更友好的文章,有必要生成文章的标题导航,让读者有个预期的阅读概览。当文章标题比较多时,手工去编写导航锚点比较费时,因此决定使用python解析Markdown文档自动生成标题导航。
知识与思路写过Markdown的人知道,Markdown的标题是使用一到六个# 左右包围住标题文字,而锚点是。 比如 ## 知识与思路 ## ,锚点连接是。标题文字允许包含空格,不过最好不要用空格或特殊不可打印字符,因为在网页上点击带锚点的链接时可能失效,并且网站对Markdown锚点的支持可能有特殊规则,比如博客园会将标题中的大写字母自动转成小写字母,并且对于有空格的标题可能无法链接到锚点。
这样,就需要解析标题行,从中提取出标题并生成锚点链接。通常使用正则表达式来匹配和提取文本内容。此外,为了排版,也要根据标题的级别生成相应的缩进。考虑到段落中很可能含有#字符,因此标题最好从第二级开始,不超过四级。
标题行的正则表达式是:
\s*(#{2,6})\s*(.*?)\s*(?:\1)\s+知识点:
2-6 个#号使用 #{2,6} 匹配; 由于行起始和标题前后都可能含有空格,因此需要使用\s*来兼容;行末尾至少有个换行符,因此要使用 \s+; 使用(subregex)捕获 subregex 匹配的文本, 使用 \1 表示后面与前面对应的被匹配的分组文本, 使用 (?:subregex) 表示匹配 subregex 的文本,但在捕获分组时忽略,不作为提取内容; 使用 (.*?) 匹配标题内容, ? 表示非贪婪模式,避免将 # 也包含到标题中; 标题的缩进比较简单,第二级的不缩进,第N级缩进 (N-2)个指定字符,这里字符选定为中文空格   代码实现 #!/usr/bin/python #_*_encoding:utf-8_*_ import re mdTitleRegex = r'\s*(#{2,6})\s*(.*?)\s*(?:\1)\s+' mdTitlePatt = re.compile(mdTitleRegex) def parseLineByRegex(line, regex_patt): m = regex_patt.match(line) return m.groups() if m else () def outputAnchor(titleTuple): if len(titleTuple) == 2: intents = '' * (len(titleTuple[0])-2) print intents,transToAnchor(titleTuple[1].decode('utf-8')) def procLine(line): outputAnchor(parseLineByRegex(line, mdTitlePatt)) def transToAnchor(title): return '[%s](#%s)' % (title, title) if __name__ == '__main__': with open('gaiyao.txt') as mdtext: mdTitles = map(procLine, mdtext.readlines())