正则表达式用法

正则表达式(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 引用前面捕获组匹配到的具体文本。

示例:匹配成对的引号

regex 复制代码
(['"]).*?\1
  • (['"]):捕获单引号或双引号,存入第 1 组。
  • .*?:非贪婪匹配中间的内容。
  • \1:引用第 1 组捕获的内容,确保结尾引号与开头一致。

命名分组 (?P<name>exp)

在 Python 等语言中,可以为分组命名,提高可读性。

  • 定义:(?P<name>pattern)
  • 引用:(?P=name) 或在替换时使用 $name / ${name}

示例:匹配 HTML 标签

regex 复制代码
<(?P<tag>\w+)>(.*?)</(?P=tag)>

非捕获组 (?:exp)

如果只需要分组功能(如应用量词),但不需要保存匹配结果,使用非捕获组可以节省内存。

  • 语法:(?:pattern)
  • 特点:不占用分组编号,无法通过 \1group() 获取内容。

应用:解析 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>

链接和图片语法相似,图片多一个前置 !

  • 图片:!\[([^\]]*)\]\(([^)\s]+)(?:\s+"([^"]*)")?\)

    • $1:Alt 文本
    • $2:图片源地址 (src)
    • $3:可选标题 (title)
    • 替换为:<img src="$2" alt="$1" title="$3" />
  • 链接:\[([^\]]*)\]\(([^)\s]+)\)

    • 替换为:<a href="$2">$1</a>

注意事项

  1. 转义特殊字符:在匹配 . * + ? ( ) [ ] { } ^ $ \ | 等元字符时,必须使用 \ 进行转义。
  2. HTML 转义:在将 Markdown 转换为 HTML 时,务必先对原始文本中的 < > & 等字符进行 HTML 实体转义,防止 XSS 注入或标签闭合错误。
  3. 非贪婪匹配:在处理包含多个相同标记的行内元素(如粗体、链接)时,务必使用非贪婪量词(*?, +?),否则正则可能会从第一个开始标记一直匹配到最后一个结束标记,导致中间内容被错误吞并。
  4. 性能考量:复杂的嵌套正则可能导致回溯灾难(ReDoS)。对于复杂的 Markdown 解析(如嵌套列表、表格、块引用),建议使用专门的解析器(如 Marked, Remarkable)而非纯正则。
  5. 测试工具:编写正则时,推荐使用在线测试工具(如 Regex101, RegExr)实时验证匹配结果和分组捕获情况。

常用语言中的调用示例 (Python)

python 复制代码
import re

text = "Hello World\nThis is bold and this is *italic*."

# 替换粗体
bold_pattern = r'(\*\*|__)([^\*\n]+?)\1'
text = re.sub(bold_pattern, r'<strong>\2</strong>', text)

# 替换斜体
italic_pattern = r'(\*|_)([^\*\n]+?)\1'
text = re.sub(italic_pattern, r'<em>\2</em>', text)

# 替换标题
header_pattern = r'^{1,6}\s+(.+)$'
def replace_header(match):
    level = len(match.group(0).split()) # 计算 的数量
    content = match.group(1)
    return f'<h{level}>{content}</h{vel}>'

text = re.sub(header_pattern, replace_header, text, flags=re.MULTILINE)

print(text)
相关推荐
营养充电站2 小时前
C++23 新特性在 CLion 中的实战体验
macos·docker·jupyter·正则表达式
吴声子夜歌13 小时前
正则表达式——字符组
正则表达式
天若有情67316 小时前
自制浏览器端文本批量处理小工具,支持查找替换、内容删除、正则表达式,开箱即用
正则表达式
吴声子夜歌21 小时前
正则表达式——简单的模式匹配
正则表达式
吴声子夜歌1 天前
正则表达式——前后查找
正则表达式
吴声子夜歌1 天前
正则表达式参考
正则表达式
吴声子夜歌2 天前
正则表达式——常见应用软件和编程语言中的正则表达式
正则表达式
吴声子夜歌2 天前
正则表达式——使用子表达式
正则表达式
吴声子夜歌3 天前
正则表达式——重复匹配
正则表达式
吴声子夜歌3 天前
正则表达式——匹配单个字符
正则表达式