3. 规则引擎基础:正则表达式语法回顾、常用模式匹配、在合同抽取中的典型应用
在采购合同条款抽取的实战中,规则引擎是构建“硬规则”的基石。正则表达式(Regular Expression, Regex)作为规则引擎的核心表达语言,能够以极高的效率从非结构化文本中定位、提取和校验特定模式。本章将系统回顾正则表达式的核心语法,展示其在合同文本中的常用匹配模式,并剖析其在条款抽取中的典型应用场景。
3.1 正则表达式核心语法速查
正则表达式由普通字符(如字母、数字)和元字符(如 .、*、+)组成。下表列出了在合同抽取中最常用的元字符及其含义:
| 元字符 | 含义 | 合同抽取示例 |
|---|---|---|
. |
匹配除换行符外的任意单个字符 | 合. 可匹配“合同”、“合约” |
* |
匹配前面的子表达式零次或多次 | 条款* 可匹配“条”、“条款”、“条款款” |
+ |
匹配前面的子表达式一次或多次 | 第\d+条 可匹配“第1条”、“第12条” |
? |
匹配前面的子表达式零次或一次 | 生效? 可匹配“生”或“生效” |
\d |
匹配一个数字字符,等价于 [0-9] |
\d{4} 可匹配“2024” |
\w |
匹配字母、数字、下划线,等价于 [a-zA-Z0-9_] |
\w+ 可匹配“甲方”、“乙方” |
\s |
匹配任何空白字符,包括空格、制表符、换页符 | \s+ 用于匹配单词间的空白 |
^ |
匹配输入字符串的开始位置 | ^第一条 匹配行首的“第一条” |
$ |
匹配输入字符串的结束位置 | 。$ 匹配句末的句号 |
[abc] |
字符集,匹配所包含的任意一个字符 | [甲乙丙] 可匹配“甲”、“乙”或“丙” |
(pattern) |
捕获组,将匹配的内容保存到分组中 | (第\d+条) 捕获条款编号 |
| |
逻辑或,匹配左右任意一个表达式 | 甲方|乙方 匹配“甲方”或“乙方” |
实战提示:在合同抽取中,
.*?(非贪婪匹配)比 .*(贪婪匹配)更常用。例如,从“甲方应于2024年12月31日前支付”中提取日期,使用 (\d{4}年\d{1,2}月\d{1,2}日) 比使用 (\d+.*日) 更精确,避免匹配到错误的内容。
3.2 合同抽取中的常用模式匹配
采购合同文本具有高度结构化的特征,常见的抽取目标包括条款编号、金额、日期、当事人名称、关键动词等。以下列举了针对这些目标的典型正则表达式模式:
- 条款编号匹配:
第[一二三四五六七八九十百千\d]+[条款]—— 可匹配“第一条”、“第1条”、“第十二款”等。 - 金额与数字匹配:
[\d,]+(\.\d{1,2})?[万]?[元]—— 可匹配“100,000.00元”、“50万元”等。 - 日期匹配:
\d{4}[-年]\d{1,2}[-月]\d{1,2}[日]?—— 可匹配“2024-12-31”、“2024年12月31日”等。 - 当事人名称匹配:
(甲方|乙方|丙方|采购方|供应方)—— 直接匹配合同主体。 - 关键动词匹配:
(应|应当|必须|不得|有权|可以)—— 用于识别义务性、禁止性或授权性条款。
案例:从以下合同文本中提取“付款期限”:
“采购方应于收到货物并验收合格后30个工作日内,向供应方支付合同总价的95%。”
正则表达式:(?<=后)[^,。]+?(?=内) —— 使用零宽断言匹配“后”与“内”之间的内容,结果为“30个工作日”。
3.3 正则表达式在合同抽取中的典型应用
在基于规则的抽取流程中,正则表达式通常用于以下三个核心环节:
- 文本预处理与清洗: 去除多余空白、统一标点符号(如将全角逗号替换为半角)、移除页眉页脚等干扰信息。
- 关键信息定位与提取: 通过编写精确的模式,从段落中定位并捕获条款编号、金额、日期、当事人等结构化字段。
- 上下文边界界定: 利用正则表达式定义条款的起始和结束边界,为后续的段落分割或深度学习模型提供精确的输入片段。
下图展示了正则表达式在合同条款抽取流水线中的典型位置与作用:
3.4 规则引擎的架构与执行流程
一个典型的基于正则表达式的规则引擎,其内部架构通常包含规则库、匹配器、上下文管理器和结果收集器四个核心模块。下图展示了各模块之间的协作关系:
避坑指南:正则表达式虽然强大,但在处理复杂、嵌套或语义模糊的条款时容易失效。例如,匹配“除……外”的排除性条款时,简单的正则可能无法正确处理嵌套结构。此时,建议将正则表达式作为第一道粗筛,再结合后续的深度学习模型进行精排与语义验证。
3.5 实战:构建一个简单的条款抽取规则
假设我们需要从采购合同中抽取“付款条件”条款。一个典型的规则构建步骤如下:
- 定义触发词: 使用正则
(付款|支付|结算)定位包含付款相关内容的段落。 - 定义金额模式: 使用
(\d+[万]?[元]?[整]?)捕获具体金额。 - 定义时间模式: 使用
(\d+[个]?[工作]?[日|月|年])捕获付款期限。 - 组合与输出: 将匹配到的金额和时间组合成结构化字段。
# Python 示例:使用正则抽取付款条件
import re
text = "甲方应于收到发票后15个工作日内,向乙方支付合同总价的90%,即450,000元。"
# 定义规则
pattern = r"(?P<trigger>支付|付款).*?(?P<amount>[\d,]+[元]?).*?(?P<period>\d+[个]?[工作]?[日|月|年])"
match = re.search(pattern, text)
if match:
print(f"触发词: {match.group('trigger')}")
print(f"金额: {match.group('amount')}")
print(f"期限: {match.group('period')}")
输出结果:
触发词: 支付
金额: 450,000元
期限: 15个工作日
关键总结:正则表达式是规则引擎的“手术刀”,精准但需要精心设计。在合同抽取实战中,建议将正则规则与词典、词性标注等传统NLP方法结合,构建多层次的硬规则体系,为后续的深度学习模型提供高质量的标注数据与候选边界。