Python regex.findall无法捕获全部短匹配?如何获取起始锚定的非全消耗匹配
解决开头锚定正则的所有前缀匹配问题
使用Python的regex库时,执行以下代码:
import regex as re matches = re.findall("^\d+", "123") print(matches) # 实际输出: ['123'] # 期望输出: ['1', '12', '123']
实际仅能得到最长匹配结果,但我们需要获取所有锚定在字符串开头的有效前缀匹配(即所有从开头截取的子串中,能匹配原正则的结果)。尝试过添加overlapped=True参数或非贪婪模式^\d+?都无法达到预期:前者输出无变化,后者仅返回['1']。
同时不想用手动截取子串的繁琐方式:
s = "123" matches = [] for length in range(len(s)+1): matches.extend(re.findall("^\d+", s[:length])) print(matches) # 输出: ['1', '12', '123'] # 但这种写法太冗余
解决方案
可以利用正向断言结合overlapped=True参数,构造通用正则表达式实现需求,无需手动截取子串。核心思路是遍历字符串每个位置,检查从开头到当前位置的子串是否匹配原正则,匹配则捕获该子串。
示例代码
import regex as re s = "123" original_pattern = r"^\d+" # 替换为你的目标正则模式 # 构造通用匹配正则 matches = re.findall(r'(?=(^.{1,}))(?=' + original_pattern + r')\1', s, overlapped=True) print(matches) # 输出: ['1', '12', '123']
原理说明
(?=(^.{1,})):正向先行断言,捕获从字符串开头到当前位置的子串(overlapped=True会让正则引擎逐个位置推进,因此这个捕获组会依次得到所有长度≥1的前缀子串)。(?=' + original_pattern + r'):正向先行断言,验证当前捕获的前缀子串是否匹配原正则模式。\1:引用第一个捕获组的内容,确保findall最终返回符合条件的前缀子串。
通用性验证
该方法适用于任意锚定开头的正则模式。比如原模式是^[A-Z]{2,},字符串是ABCDE:
s = "ABCDE" original_pattern = r"^[A-Z]{2,}" matches = re.findall(r'(?=(^.{1,}))(?=' + original_pattern + r')\1', s, overlapped=True) print(matches) # 输出: ['AB', 'ABC', 'ABCD', 'ABCDE']
内容的提问来源于stack exchange,提问作者Artie Vandelay
相关产品推荐
相关产品推荐

