正则表达式用法

正则表达式(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)
相关推荐
GuWen_yue1 天前
正则表达式(Regex)通用相关知识点
正则表达式
meilindehuzi_a1 天前
打破0基础:通过 5 个核心案例深度拆解 JavaScript 正则表达式与运行时类型系统
开发语言·javascript·正则表达式
sugar__salt2 天前
JS正则表达式与字符串高阶实战精讲
开发语言·javascript·正则表达式
FBI HackerHarry浩3 天前
第二阶段Day07【Python生成器、yield关键字、property、正则表达式】
开发语言·python·正则表达式
曾阿伦3 天前
Unicode 正则表达式开发指南
python·正则表达式
程序大视界4 天前
【Python系列课程】Python正则表达式(下):环视、命名分组与日志实战
开发语言·python·正则表达式
超梦dasgg5 天前
Java 正则表达式 完整详解(语法 + 核心类 + 常用方法 + 实战案例)
java·开发语言·正则表达式
之歆7 天前
Day24_JavaScript正则表达式与性能优化实战:从入门到精通
javascript·性能优化·正则表达式
羑悻的小杀马特8 天前
【动态规划篇】正则表达式与通配符:开启代码匹配的赛博奇幻之旅
c++·算法·leetcode·正则表达式