大数据

正则知识点回顾

一、正则知识点梳理

1. 基础元字符

元字符含义示例
^匹配字符串开头^abc 匹配以abc开头
$匹配字符串结尾abc$ 匹配以abc结尾
.匹配除换行符外任意字符a.c 匹配abc、a1c
\d匹配数字(0-9)\d+ 匹配123
\s匹配空白字符(空格、制表符等)a\sb 匹配"a b"
\w匹配单词字符(字母数字下划线)\w+ 匹配abc_123

2. 字符类 []

含义示例
[abc]匹配a、b、c中任意一个[abc] 匹配"a"
[a-z]匹配a到z任意小写字母[a-z] 匹配"m"
[0-9]匹配任意数字[0-9] 匹配"5"
[\u4e00-\u9fff]匹配中文汉字[\u4e00-\u9fff]+ 匹配"你好"
[,,::。;;()()]匹配中英文标点匹配逗号、冒号等

3. 量词

量词含义示例
*0次或多次a* 匹配""、"a"、"aa"
+1次或多次a+ 匹配"a"、"aa",不匹配""
?0次或1次a? 匹配""或"a"
{n}恰好n次\d{3} 匹配"123"
{n,m}n到m次\d{2,4} 匹配"12"、"1234"

4. 分组与选择

写法含义示例
(?:...)非捕获分组(只分组不捕获)(?:abc|def) 匹配abc或def
(a|b)捕获分组 + 选择(a|b) 匹配a或b,并捕获
|或(选择)业务|系统 匹配"业务"或"系统"

5. 关键区别:?: 的作用

import re

# 捕获分组:会保存匹配结果
m = re.search(r'(业务|系统)流程', '业务流程')
print(m.group(1))  # 输出: 业务

# 非捕获分组:不保存,提高性能
m = re.search(r'(?:业务|系统)流程', '业务流程')
print(m.group(1))  # 报错!因为没有捕获组

Demo 1: 基础语法演练

import re

print("=" * 50)
print("Demo 1: 基础元字符和字符类")
print("=" * 50)

# 1. \d 匹配数字
text = "图1 业务流程图"
result = re.search(r'图\s*(\d+)', text)
print(f"文本:{text}")
print(f"匹配数字:{result.group(1) if result else ''}")

# 2. \s 匹配空白
text2 = "图 2-1"
result2 = re.search(r'图\s*\d+', text2)
print(f"文本:{text2}")
print(f"匹配数字:{result2.group() if result else ''}")

# 3. [] 字符类 - 中英文标点
text3 = "如图所示:"
result3 = re.search(r'所示[::。;;,,()()]*', text3)
print(f"文本: {text3}")
print(f"匹配标点: {result3.group() if result3 else ''}")

# 4. [\u4e00-\u9fff] 匹配中文
text4 = "业务流程系统-简介"
result4 = re.findall(r'[\u4e00-\u9fff]+', text4)
print(f"文本: {text4}")
print(f"匹配中文: {result4}")

Demo 2: 量词使用

import re

print("=" * 50)
print("Demo 2: 量词 * + ? 的区别")
print("=" * 50)

# * 0次或多次
print("--- * 匹配0次或多次 ---")
pattern_star = r'图\s*\d+'
print(f"模式:{pattern_star}")
print(f"'图1' -> {re.search(pattern_star, '图1').group()}")
print(f"'图 1' -> {re.search(pattern_star, '图 1').group()}")
print(f"'图  1' -> {re.search(pattern_star, '图  1').group()}")

# + 次或多次
print("\n--- + 匹配1次或多次 ---")
pattern_plus = r'图\s+\d+'
print(f"模式:{pattern_plus}")
print(f"'图1' -> {re.search(pattern_plus, '图1')}")
print(f"'图 1' -> {re.search(pattern_plus, '图 1').group()}")
print(f"'图  1' -> {re.search(pattern_plus, '图  1').group()}")

# ? 0次或1次
print("\n--- ? 匹配0次或1次 ---")
pattern_question = r'(?:如图)?图\s*\d+'
print(f"模式: {pattern_question}")
print(f"'图1' -> {re.search(pattern_question, '图1').group()}")
print(f"'如图1' -> {re.search(pattern_question, '如图1').group()}")
print(f"'如图图1' -> {re.search(pattern_question, '如图图1')}")

Demo 3: 分组与选择(核心知识点)

import re

print("=" * 50)
print("Demo 3: 分组与选择 (| 和 ?:)")
print("=" * 50)

# 1 选择 | 匹配多种可能性
texts = [
    "业务流程图如下所示",
    "系统流程图如下所示",
    "操作流程图如下所示",
    "流程图如下所示"
]

pattern = r'^(?:业务|系统|操作)?流程图如下所示'
print("模式: ^(?:业务|系统|操作)?流程图如下所示")
print("-" * 40)
for text in texts:
    result = re.search(pattern, text)
    print(f"'{text}' -> {'匹配' if result else '不匹配'}")
print("\n")

# 2. 捕获分组 vs 非捕获分组
text = "业务流程图如下所示"

# 捕获分组
pattern_capture = r'^(业务|系统|操作)?流程图如下所示'
result = re.search(pattern_capture, text)
if result:
    print(f"捕获分组结果:{result.group(1)}")

# 非捕获分组
pattern_non_capture = r'^(?:业务|系统|操作)?流程图如下所示'
result = re.search(pattern_non_capture, text)
print(f"非捕获分组结果:{result.group(0)}")

# 3 复杂选择示例
pattern_complex = r'(?:|参见|详见|)?图\s*\d+(?:[--]\d+)?'
test_texts = [
    "见图1",
    "参见图2",
    "详见图3-1",
    "如图4所示",
    "图5"
]
print("模式: (?:见|参见|详见|如)?图\s*\d+(?:[--]\d+)?")
print("-" * 40)

for t in test_texts:
    result = re.search(pattern_complex, t)
    print(f"'{t}' -> {result.group() if result else '不匹配'}")

Demo 4: 实战 - 提取图片引用

import re

print("=" * 50)
print("Demo 4: 实战 - 从文本中提取图片引用")
print("=" * 50)

# 组合所有短语匹配规则
phrase_patterns = [
    r"[((]\s*(?:|参见|)?图\s*\d+(?:[--]\d+)?(?:所示||)?\s*[))]",
    r"(?:如图|见图|参见图|详见图)\s*\d+(?:[--]\d+)?(?:所示)?[,,::。;;]*",
    r"(?:|)?图\s*\d+(?:[--]\d+)?(?:||所示)[,,::。;;]*",
    r"(?:)图\s*\d+(?:\s*[--]\s*\d+)?\s*(?:)?\s*可以(?:看出|看到)[,,::。;;]*",
    r"\s*(?:如上图|如图下图|图下图|如下图|如图|下图|上图)(?:所示|)?[,,::。;;]*\s*$"
]

# 合并为一个正则用 | 连接
combined_pattern = '|'.join(phrase_patterns)
print("合并后的正则(简化显示):")
print(combined_pattern[:100] + "...\n")

# 测试文本
test_article = """
系统架构设计采用了微服务模式(见图1),各服务之间通过消息队列通信。
如图2所示,整体流程分为三个阶段:数据采集、处理、展示。
从图3中可以看出,核心模块包括用户管理、订单处理、数据分析。
图4还可以看出,系统响应时间明显优化。
整体的设计方案如下图所示。
详细配置请参考(参见图5-1)。
从图2-1还可以看到,性能提升了30%。
"""

print("测试文本:")
print("-" * 40)
print(test_article)
print("-" * 40)

# 提取所有匹配
matches = re.findall(combined_pattern, test_article, re.MULTILINE)
print(f"\n找到 {len(matches)} 个图片引用:")
for i, match in enumerate(matches, 1):
    # 注意: findall 返回元组列表(因为多个分组)
    # 这里我们取非空的那个
    actual_match = next((m for m in match if m), match[0] if match else '')
    print(f"  {i}. {actual_match}")

# 更好的方式:使用finditer 获取完整匹配
print("使用finditer 提取完整匹配")
print("-" * 40)
for i, match in enumerate(re.finditer(combined_pattern, test_article, re.MULTILINE), 1):
    print(f"  {i}. {match.group(0).strip()}")

Demo 5: 行匹配 vs 短语匹配

import re

print("=" * 50)
print("Demo 5: 行匹配 vs 短语匹配 对比")
print("=" * 50)

# 行匹配规则(通常单独成行)
line_patterns = [
    r"^(?:[\u4e00-\u9fffA-Za-z0-9]+)?(?:业务|系统|整体|总体|操作|处理|管理|资产|会员管理|礼券管理)?(?:流程图|蓝图|示意图|截图|图片)(?:如下|如下所示|如下图所示)[::。;;,,()()图]*$",
    r"^(?:如下图|下图|上图|见下图|如图)(?:所示)?[::。;;,,()()图]*$",
    r"^(?:业务|系统|整体|总体|操作|处理|管理|资产)?流程图如下所示[::。;;,,()()图]*$",
    r"^图\s*\d+(?:[--]\d+)?\s*.*$"
]
line_combined = '|'.join(line_patterns)

phrase_patterns = [
    r"[((]\s*(?:|参见|详见|)?图\s*\d+(?:[--]\d+)?(?:所示||)?\s*[))]",
    r"(?:如图|见图|参见图|详见图)\s*\d+(?:[--]\d+)?(?:所示)?[,,::。;;]*",
    r"(?:|)?图\s*\d+(?:[--]\d+)?(?:||所示)[,,::。;;]*",
    r"(?:)?图\s*\d+(?:\s*[--]\s*\d+)?\s*(?:)?\s*可以(?:看出|看到)[,,::。;;]*",
    r"\s*(?:如上图|如图下图|图下图|如下图|如图|下图|上图)(?:所示|)?[,,::。;;]*\s*$"
]

# 短语匹配规则(嵌入在段落中)
phrase_combined = '|'.join(phrase_patterns)

test_document = """
第一章 系统概述

业务流程图如下所示:
(见图1)

系统架构采用分层设计,如图2所示,分为展示层、业务层、数据层。

图3 系统部署架构

从图4中可以看出,数据库采用主从复制方案。

如图5所示,整体流程清晰。
"""

print("测试文档:")
print("=" * 40)
print(test_document)
print("=" * 40)

# 行匹配
print("\n【行匹配结果】- 匹配独立成行的引用:")
line_matches = re.finditer(line_combined, test_document, re.MULTILINE)
for i, m in enumerate(line_matches, 1):
    print(f"  {i}. {m.group(0).strip()}")

# 短语匹配
print("\n【短语匹配结果】- 匹配段落中的引用:")
phrase_matches = re.finditer(phrase_combined, test_document, re.MULTILINE)
for i, m in enumerate(phrase_matches, 1):
    print(f"  {i}. {m.group(0).strip()}")

print("\n")
print("总结:")
print("- 行匹配: 匹配标题/描述行,如 '业务流程图如下所示:'、'图3 系统部署架构'")
print("- 短语匹配: 匹配段落中的引用,如 '(见图1)'、'如图2所示'、'从图4中可以看出'")

Demo 6: 正则调试技巧

import re

print("=" * 50)
print("Demo 6: 调试技巧 - 逐步构建正则")
print("=" * 50)


def test_pattern(pattern, test_cases, description=""):
    """测试正则匹配的辅助函数"""
    print(f"\n{description}")
    print(f"模式: {pattern}")
    print("-" * 40)
    for text in test_cases:
        result = re.search(pattern, text)
        status = "" if result else ""
        matched = f" -> '{result.group()}'" if result else ""
        print(f"  {status} '{text}'{matched}")

# 案例:构建匹配“图1所示”的正则
# 步骤1 匹配基本格式
step1 = r"图\s*\d+"
test_cases = ["图1", "图 1", "图1所示", "图2-1", "图A"]
test_pattern(step1, test_cases, "步骤1: 匹配 '图+数字'")

# 步骤2 添加可选的后缀
step2 = r"图\s*\d+(?:所示)?"
test_cases = ["图1", "图1所示", "图2", "图2所示", "图1中"]
test_pattern(step2, test_cases, "步骤2: 添加可选的 '所示'")

# 步骤3 添加可选的如
step3 = r"(?:)?图\s*\d+(?:所示)?"
test_cases = ["图1", "如图1", "如图1所示", "图2所示", "见图1"]
test_pattern(step3, test_cases, "步骤3: 添加可选的 '如'")

# 步骤4 完整版本
step4 = r"(?:如图|见图|参见图|详见图)?\s*\d+(?:[--]\d+)?(?:所示)?"
test_cases = [
    "图1",
    "如图1",
    "见图2-1",
    "参见图3所示",
    "详见图4",
    "图A"
]
test_pattern(step4, test_cases, "步骤4: 完整版本 - 多种前缀 + 可选子图号")

三、核心要点总结

知识点你的正则中的体现
^ $行匹配模式使用,确保整行匹配
\s*大量使用,匹配可能存在的空格
\d+匹配图片编号,如 图1图2-1
[\u4e00-\u9fff]匹配中文关键词
(?:a|b|c)非捕获分组 + 选择,匹配多种关键词
? 量词让前缀/后缀变为可选
[...] 字符类匹配各种中英文标点符号