为何非贪婪正则Pattern出现贪婪匹配效果,误选非目标文本行?
正则误匹配原因
你的正则表达式存在两处核心问题,直接导致第二行不符合预期的内容被选中:
- 词性匹配未做边界限制:正则开头的
/NN没有限定匹配范围,所有包含/NN字符片段的词性标注都会被命中,包括预期外的/NNS(复数名词)、/NN/I-NP(名词短语内部名词)等标注形式。 - 匹配规则允许跨词遍历:正则中使用的
.+?属于非贪婪通配符,可以匹配任意字符(包括空格、斜杠、其他词的标注内容),不会强制要求目标的「名词-动词-名词」是连续相邻的句法成分。
对应第二行的句法解析结果,正则的完整匹配路径为:- 首先命中
performance/NN/I-NP/O中的/NN片段 - 向后跨
/I-NP/O they/PRP/I-NP/O put这段内容,命中put/VB/B-VP/O中的/VB/B-VP片段 - 再向后跨
/O on/IN/B-PP/B-PNP at/IN/I-PP/I-PNP her/PRP$/B-NP/I-PNP school这段内容,命中school/NN/I-NP/I-PNP中的/NN片段
整条路径完全符合正则规则,因此第二行被误判为匹配项。
- 首先命中
修正方案
如果要精准匹配「名词-起始VP动词-名词」的连续三词结构,需要给正则增加边界限制,禁止跨词匹配、避免误匹配衍生词性,参考写法如下:
# 同时匹配单复数名词(NN/NNS)的连续结构,适配你当前预期匹配第一行的需求 pattern = re.compile(r'/NN[S]?/[^ ]+ [^ ]+/VB/B-VP[^ ]* [^ ]+/NN[S]?/') # 如果只需要匹配单数名词(NN),删掉正则里的[S]?即可 # pattern = re.compile(r'/NN/[^ ]+ [^ ]+/VB/B-VP[^ ]* [^ ]+/NN/')
该写法用[^ ]+匹配单个词标注内的剩余内容,强制三个目标成分必须是相邻的三个词,不会跨无关词匹配,运行测试用例时只会命中符合预期的句子。
内容的提问来源于stack exchange,提问作者blackantt
相关产品推荐
相关产品推荐

