正则表达式用法
正则表达式Regular Expression简称 Regex是一种强大的文本处理工具用于匹配、查找、替换和提取字符串中的特定模式。它广泛应用于编程、数据清洗、日志分析以及 Markdown 解析等场景。基础语法元素正则表达式由普通字符和元字符组成。以下是核心语法的分类说明预定义字符类字符含义等价形式.匹配除换行符以外的任意字符-\d匹配数字字符[0-9]\D匹配非数字字符[^0-9]\w匹配单词字符字母、数字、下划线[a-zA-Z0-9_]\W匹配非单词字符[^a-zA-Z0-9_]\s匹配空白字符空格、Tab、换行等[\t\n\x0B\f\r]\S匹配非空白字符[^\t\n\x0B\f\r]边界匹配字符含义^匹配字符串的开头$匹配字符串的结尾\b匹配单词边界\B匹配非单词边界量词重复匹配字符含义*匹配前一个元素 0 次或多次匹配前一个元素 1 次或多次?匹配前一个元素 0 次或 1 次{n}匹配前一个元素恰好 n 次{n,}匹配前一个元素至少 n 次{n,m}匹配前一个元素 n 到 m 次注意默认情况下量词是贪婪模式尽可能多匹配。在量词后加?如*?,?可变为非贪婪模式尽可能少匹配这在解析嵌套结构如 HTML/Markdown 标签时非常重要。分组与捕获分组允许将多个字符视为一个整体进行重复匹配并可以“捕获”匹配到的内容供后续使用。捕获组(exp)使用圆括号()包裹的子表达式称为捕获组。正则引擎会记录匹配到的内容并分配编号。编号规则从左到右根据左括号出现的顺序编号从 1 开始。整个表达式默认为第 0 组。反向引用在正则表达式内部可以使用\1,\2引用前面捕获组匹配到的具体文本。示例匹配成对的引号([]).*?\1([])捕获单引号或双引号存入第 1 组。.*?非贪婪匹配中间的内容。\1引用第 1 组捕获的内容确保结尾引号与开头一致。命名分组(?Pnameexp)在 Python 等语言中可以为分组命名提高可读性。定义(?Pnamepattern)引用(?Pname)或在替换时使用$name/${name}示例匹配 HTML 标签(?Ptag\w)(.*?)/(?Ptag)非捕获组(?:exp)如果只需要分组功能如应用量词但不需要保存匹配结果使用非捕获组可以节省内存。语法(?:pattern)特点不占用分组编号无法通过\1或group()获取内容。应用解析 Markdown 语法正则表达式常用于轻量级的 Markdown 到 HTML 转换。以下是常见元素的解析思路标题 (Headers)Markdown 标题以 开头后跟空格和文本。正则^{1,6}\s(.)$(需开启多行模式)替换为h$1$2/h$1$1捕获 的数量1-6决定标题级别。$2捕获标题文本。强调 (Emphasis)粗体 (text或__text__)正则(\*\*|__)([^\*\n]?)\1替换为strong$2/strong说明\1确保结束标记与开始标记一致都是**或都是__?使用非贪婪匹配防止跨行误捕。斜体 (*text*或_text_)正则(\*|_)([^\*\n]?)\1替换为em$2/em行内代码 (Inline Code)正则([^\n])替换为code$1/code链接与图片 (Links Images)链接和图片语法相似图片多一个前置!。图片!\[([^\]]*)\]\(([^)\s])(?:\s([^]*))?\)$1Alt 文本$2图片源地址 (src)$3可选标题 (title)替换为img src$2 alt$1 title$3 /链接\[([^\]]*)\]\(([^)\s])\)替换为a href$2$1/a注意事项转义特殊字符在匹配.*?()[]{}^$\|等元字符时必须使用\进行转义。HTML 转义在将 Markdown 转换为 HTML 时务必先对原始文本中的等字符进行 HTML 实体转义防止 XSS 注入或标签闭合错误。非贪婪匹配在处理包含多个相同标记的行内元素如粗体、链接时务必使用非贪婪量词*?,?否则正则可能会从第一个开始标记一直匹配到最后一个结束标记导致中间内容被错误吞并。性能考量复杂的嵌套正则可能导致回溯灾难ReDoS。对于复杂的 Markdown 解析如嵌套列表、表格、块引用建议使用专门的解析器如 Marked, Remarkable而非纯正则。测试工具编写正则时推荐使用在线测试工具如 Regex101, RegExr实时验证匹配结果和分组捕获情况。常用语言中的调用示例 (Python)importre textHello World\nThis is bold and this is *italic*.# 替换粗体bold_patternr(\*\*|__)([^\*\n]?)\1textre.sub(bold_pattern,rstrong\2/strong,text)# 替换斜体italic_patternr(\*|_)([^\*\n]?)\1textre.sub(italic_pattern,rem\2/em,text)# 替换标题header_patternr^{1,6}\s(.)$defreplace_header(match):levellen(match.group(0).split())# 计算 的数量contentmatch.group(1)returnfh{level}{content}/h{vel}textre.sub(header_pattern,replace_header,text,flagsre.MULTILINE)print(text)