re.findall匹配异常:提取YAML键值对无法捕获全部值
解决正则提取YAML键值对时重复捕获组的问题
嘿,我来帮你搞定这个正则匹配的问题~你遇到的其实是正则里重复捕获组的经典陷阱:当你给捕获组(也就是带括号的(...))加上重复量词(比如*)时,正则引擎只会保留这个分组最后一次匹配的结果,之前的匹配内容会被直接覆盖,所以你只能拿到最后一个- valueX项,这就是为什么结果和预期不符的原因。
下面给你两种解决方案,按需选择:
方案一:用正则先捕获整块再拆分值项
如果你坚持想用正则处理,可以先把每个键对应的整个值块捕获下来,再手动拆分成单个值项。这里要用到非捕获组(?:...),它用来重复匹配值项但不会单独捕获,避免覆盖问题:
import re text = """key1: - value1 - value2 key1: - value1 - value2 - value3""" # 匹配每个键值对的整块,非捕获组处理重复的value行 matches = re.findall(r'^(.*):\n((?:- .*\n)+)', text, re.MULTILINE) result = [] for key, values_block in matches: # 把值块拆分成单个value项 values = [line.strip() for line in values_block.strip().split('\n')] result.append((key, *values)) print(result) # 输出:[('key1', '- value1', '- value2'), ('key1', '- value1', '- value2', '- value3')]
你也可以用re.finditer遍历每个匹配对象,更灵活地处理每一块:
result = [] pattern = re.compile(r'^(.*):\n((?:- .*\n)+)', re.MULTILINE) for match in pattern.finditer(text): key = match.group(1) values = match.group(2).strip().split('\n') result.append((key, *values))
方案二:用专业YAML解析库(更推荐)
正则处理YAML其实非常脆弱——如果遇到缩进变化、多行值、注释或者更复杂的YAML语法,正则很容易失效。更靠谱的方式是用专门的YAML解析库,比如PyYAML:
首先安装库:
pip install pyyaml
然后编写代码,注意YAML默认不允许重复键,所以需要自定义加载器来保留重复键的信息:
import yaml text = """key1: - value1 - value2 key1: - value1 - value2 - value3""" # 自定义加载器,保留重复键的键值对 class DuplicateKeyLoader(yaml.FullLoader): def construct_mapping(self, node, deep=False): mapping = [] for key_node, value_node in node.value: key = self.construct_object(key_node, deep=deep) value = self.construct_object(value_node, deep=deep) mapping.append((key, value)) return mapping # 加载YAML文本 data = yaml.load(text, Loader=DuplicateKeyLoader) print(data) # 输出:[('key1', ['value1', 'value2']), ('key1', ['value1', 'value2', 'value3'])]
这种方式不仅能正确处理重复键,还会自动把值转换成列表,比正则更稳定、更易维护。
内容的提问来源于stack exchange,提问作者Maaike
相关产品推荐
相关产品推荐

