如何用Python正则捕获含缩写的重叠双词序列?及模式调整方案
嘿,很高兴帮你解决这两个正则相关的问题!
问题1:编写可捕获含缩写重叠双词序列的Python正则表达式
要捕获文本中包含缩写(比如can't、won't这类带撇号的形式)的重叠双词序列,关键要解决两个核心点:一是正确定义能识别缩写的“词”,二是实现重叠匹配(也就是滑动窗口式的连续双词,比如one can't之后紧接着匹配can't two)。
这里给出一个实用的正则方案:
import re text = "one can't two won't three" # 正则逻辑拆解: # - (?=...) 正向预查:不消耗字符,实现重叠匹配的核心 # - (?:^|(?<=\s)) 确保词的开头是字符串起始或空白,避免从词内部开始匹配 # - [\w\'’-]+ 匹配包含字母、撇号、连字符的词,覆盖缩写和带连字符的词 # - (?:(?=\s)|(?=$)) 确保词的结尾是空白或字符串结束,避免匹配词的一部分 pattern = r'(?=((?:^|(?<=\s))[\w\'’-]+ [\w\'’-]+(?:(?=\s)|(?=$))))' matches = re.findall(pattern, text) print(matches) # 输出: ["one can't", "can't two", "two won't", "won't three"]
核心思路:
- 用正向预查
(?=...)实现重叠:普通正则匹配会消耗字符,导致无法捕获重叠的序列,而预查只是检查后续内容是否符合,不会移动匹配指针,所以能逐个位置滑动检查。 - 自定义词的边界:用
(?:^|(?<=\s))和(?:(?=\s)|(?=$))替代原生的\b,避免\b在缩写内部(比如can't里的'和t之间)误触发匹配。 - 词的匹配范围:
[\w\'’-]+覆盖了常见的缩写(带撇号)、普通单词,以及带连字符的词(比如mother-in-law)。
问题2:调整现有正则以得到期望输出
先分析你给出的代码问题:原正则里的\b(单词边界)是导致错误输出的根源。因为\b的定义是\w(字母/数字/下划线)和非\w字符的边界,而缩写里的'属于非\w,所以can't内部会出现两个\b(n和'之间、'和t之间)。这导致正则会在'后面的位置尝试匹配,把t当成一个独立的词,从而出现t two、t three这类错误结果。
调整后的正则方案
只需要把原生的\b替换为基于空白/字符串首尾的自定义边界,就能避免内部误匹配:
from re import findall s= '''one can't two won't three''' # 调整后的正则:用空白/首尾限定词的边界,避免内部误匹配 pat = r'(?=((?:(?<=^)|(?<=\s))[\w\'’-]+ [\w\'’-]+(?:(?=\s)|(?=$))))' s2 = findall(pat, s) print(s2) # 期望输出: ["one can't", "can't two", "two won't", "won't three"]
调整细节解释:
(?:(?<=^)|(?<=\s)):确保当前位置的前一个字符是字符串开头或者空白,这样就不会从can't里的'后面开始匹配(因为'不是空白)。(?:(?=\s)|(?=$)):确保当前位置的后一个字符是空白或者字符串结尾,避免把词的一部分当成完整词。- 保留
[\w\'’-]+:确保能正确匹配带撇号、连字符的缩写和单词。
内容的提问来源于stack exchange,提问作者Nicholas Nickleby
相关产品推荐
相关产品推荐

