Python3中如何用re模块从指定格式字符串提取多组数字?
问题分析与解决方案
嘿,这个正则陷阱我之前踩过!咱们先搞清楚为啥你的正则只返回最后一个数字,再给你几个靠谱的解决办法~
问题出在哪?
你写的正则 r"add/(?:(\d+)/){3,}" 里,(\d+) 这个捕获组被放在了重复的非捕获组 (?:...){3,} 内部。当正则引擎处理重复量词(比如 {3,})时,每次重复都会覆盖捕获组的内容——也就是说,第一次匹配到10存在组1里,第二次匹配20就把组1的内容替换成20,直到最后一次匹配9,组1里就只剩9了。这就是为什么findall只返回最后一个数字。
解决办法
方法1:先提取整体,再拆分(最直观)
先把add/后面的所有内容提取出来,再按/拆分过滤掉空字符串,简单易懂:
import re s1 = 'add/10/20/30/4/3/9/' s2 = 'add/10/20/30/' # 匹配add开头,后面跟着任意内容(直到结尾或最后一个/) match = re.match(r'add/(.*?)/?$', s1) if match: num_list = [num for num in match.group(1).split('/') if num] print(num_list) # 输出 ['10', '20', '30', '4', '3', '9'] # 测试第二个字符串 match2 = re.match(r'add/(.*?)/?$', s2) if match2: num_list2 = [num for num in match2.group(1).split('/') if num] print(num_list2) # 输出 ['10', '20', '30']
方法2:直接全局匹配符合位置的数字
用正向断言限定数字的位置,确保它们在add/后面的路径段里,直接提取所有数字:
import re s1 = 'add/10/20/30/4/3/9/' s2 = 'add/10/20/30/' # 正向回溯断言:数字前面是add/或者/;正向前瞻:数字后面是/ num_list = re.findall(r'(?<=add/|/)\d+(?=/)', s1) print(num_list) # ['10', '20', '30', '4', '3', '9'] num_list2 = re.findall(r'(?<=add/|/)\d+(?=/)', s2) print(num_list2) # ['10', '20', '30']
方法3:用finditer遍历匹配(适合复杂场景)
如果需要更精细的控制,可以用re.finditer遍历所有符合条件的数字匹配,灵活性更高:
import re s = 'add/10/20/30/4/3/9/' num_list = [match.group() for match in re.finditer(r'\d+', s) if match.start() > len('add/')] print(num_list) # ['10', '20', '30', '4', '3', '9']
总结
核心坑点就是重复捕获组会覆盖之前的结果,所以尽量避免在带重复量词的组内部放捕获组。上面的几种方法里,方法1最适合新手理解,方法2更简洁高效,根据你的场景选就行~
内容的提问来源于stack exchange,提问作者Yannick
相关产品推荐
相关产品推荐

