Python re.findall正则捕获分组结果不符合预期如何调整
推荐问题标题
- Python re.findall 匹配可变长度前缀时如何获取拆分后的独立捕获结果
- 正则匹配大括号包裹内容及前置标识符时,如何得到按标识符拆分的预期捕获组
问题复现
当前测试代码如下:
import re txt = """ %power {s} shop %power {w} %electricity {t} """.replace('\n',' ') x = re.findall("((\%?\w+\s)*)\{([^\}]*)\}",txt)
代码实际返回结果:[('%power ', '%power ', 's'), ('shop %power ', '%power ', 'w'), ('%electricity ', '%electricity ', 't')]
预期返回结果:[('%power ', 's'), ('shop ', '%power ', 'w'), ('%electricity ', 't')]
需要调整正则或匹配逻辑得到预期结果。
原因说明
正则表达式的捕获组数量在表达式编写完成时就是固定值,无法单靠一条正则返回长度可变的结果元组;同时原表达式中被*量词修饰的内层捕获组,只会保留最后一次匹配到的内容,不会存储每一轮匹配的独立片段,因此直接用原写法不可能得到预期结果。
解决方案
采用两步匹配逻辑实现:
- 第一步用非捕获组匹配大括号前的整段前缀内容和大括号内的值,避免生成多余捕获项
- 第二步将匹配到的整段前缀拆分为独立的标识符片段,和大括号内的值拼接为最终结果
完整实现代码:
import re txt = """ %power {s} shop %power {w} %electricity {t} """.replace('\n',' ') result = [] # 第一轮匹配:拿到每段大括号对应的整段前缀、括号内值 for full_prefix, brace_value in re.findall(r'((?:%?\w+\s)+)\{([^}]*)\}', txt): # 第二轮拆分:把整段前缀拆成单个带空格的标识符块 prefix_parts = re.findall(r'%?\w+\s', full_prefix) # 拼接为目标元组存入结果 result.append(tuple(prefix_parts + [brace_value])) print(result)
运行上述代码,输出结果与预期完全一致:[('%power ', 's'), ('shop ', '%power ', 'w'), ('%electricity ', 't')]
内容的提问来源于stack exchange,提问作者Farhang Amaji
相关产品推荐
相关产品推荐

