使用Python RegEx的finditer提取键值对时匹配不全的问题排查
从字符串提取顶层$开头键值对的正则问题
我有一段包含多组键值对的示例字符串,希望从中提取所有键值对。以下是我的代码片段:
import re sample_string = r""" $key1 = 'val1'; $key2 = 'val2'; $key3 = 'val3'; $key4 = 'val4'; $key5 = ( { key1 => 'val1', key2 => 'val2', }, ); """ reg_exp = re.compile(r"\$(.+?)\s*=\s*(.*?);") for match in reg_exp.finditer(sample_string, re.MULTILINE | re.DOTALL): ss = match.groups() print(ss)
但这段代码仅识别出部分键值对:
('key3', "'val3'") ('key4', "'val4'")
请问我遗漏了什么?
问题分析与解决
1. flags参数传递错误
你在finditer中把re.MULTILINE | re.DOTALL作为第二个参数传入,但re.finditer的第二个参数是匹配的起始位置pos,并非flags参数。这导致正则从字符串的第24个字符(re.MULTILINE=8,re.DOTALL=16,两者相加为24)开始匹配,直接跳过了前两个$key1和$key2,所以只捕获到了后面的$key3和$key4。
正确的做法是在编译正则时添加flags,或者在finditer中使用关键字参数flags=...。
2. 正则表达式的匹配逻辑缺陷
原正则\$(.+?)\s*=\s*(.*?);的非贪婪匹配.*?在开启re.DOTALL后,会在遇到第一个分号时停止匹配,无法正确捕获$key5这种多行嵌套结构的完整值。
修正后的代码
import re sample_string = r""" $key1 = 'val1'; $key2 = 'val2'; $key3 = 'val3'; $key4 = 'val4'; $key5 = ( { key1 => 'val1', key2 => 'val2', }, ); """ # 编译时指定flags,调整正则以匹配多行值 reg_exp = re.compile(r"\$(\w+)\s*=\s*([\s\S]*?);", re.DOTALL) for match in reg_exp.finditer(sample_string): print(match.groups())
如果要避免值内部的分号干扰(比如值本身包含分号的场景),可以用更严谨的逻辑(Python原生正则不支持平衡组,这里用负向预查适配示例结构):
reg_exp = re.compile(r"\$(\w+)\s*=\s*(.*?)(?<!,);", re.DOTALL)
修正后的输出
('key1', "'val1'") ('key2', "'val2'") ('key3', "'val3'") ('key4', "'val4'") ('key5', "( { key1 => 'val1', key2 => 'val2', }, )")
内容的提问来源于stack exchange,提问作者ManiAm
相关产品推荐
相关产品推荐

