You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何忽略含嵌套括号的区域,按空格和冒号分割字符串?

解决嵌套括号场景下的键值对提取问题

问题分析

你需要从包含嵌套圆括号()和花括号{}的字符串中提取键值对,要求分割时忽略括号内部的空格和冒号。之前的正则无法处理嵌套括号,导致括号内的内容被误分割。

示例目标:从字符串

p1: I/out   p2: (('mean', 5), 0.0, ('std', 2))   p3: 7   p4: {'name': 'check', 'value': 80.0}

中提取出:

  • p1: I/out
  • p2: (('mean', 5), 0.0, ('std', 2))
  • p3: 7
  • p4: {'name': 'check', 'value': 80.0}

方案1:使用支持递归的正则匹配(推荐用Python regex库)

标准Python的re模块不支持递归正则,但第三方regex库可以处理嵌套结构。安装后用以下正则直接匹配所有键值对:

import regex

s = "p1: I/out   p2: (('mean', 5), 0.0, ('std', 2))   p3: 7   p4: {'name': 'check', 'value': 80.0}"
pattern = r'(\w+):\s*((?:[^(){}\s]+|\((?:(?R))*\)|\{(?:(?R))*\})+)'
matches = regex.findall(pattern, s)

# 转换为字典或列表
result = dict(matches)
print(result)

输出:

{'p1': 'I/out', 'p2': "(('mean', 5), 0.0, ('std', 2))", 'p3': '7', 'p4': "{'name': 'check', 'value': 80.0}"}

正则说明:

  • (\w+):匹配键名(如p1、p2)
  • :\s*:匹配冒号和后续空格
  • ((?:[^(){}\s]+|\((?:(?R))*\)|\{(?:(?R))*\})+):匹配值部分,其中:
    • [^(){}\s]+:匹配非括号非空格的内容
    • \((?:(?R))*\):递归匹配圆括号内的所有内容(包括嵌套)
    • \{(?:(?R))*\}:递归匹配花括号内的所有内容(包括嵌套)

方案2:手动解析(无第三方库依赖)

如果不想用第三方库,可以手动遍历字符串,跟踪括号的嵌套层级,确定分割点:

def extract_key_value_pairs(s):
    pairs = []
    current_key = []
    current_value = []
    in_quotes = False
    bracket_stack = []
    
    for char in s:
        # 处理引号(避免把引号内的括号当成嵌套)
        if char in ('"', "'"):
            in_quotes = not in_quotes
            current_value.append(char)
            continue
        
        if in_quotes:
            current_value.append(char)
            continue
        
        # 处理括号嵌套
        if char in ('(', '{'):
            bracket_stack.append(char)
            current_value.append(char)
            continue
        if char in (')', '}'):
            if bracket_stack and ((char == ')' and bracket_stack[-1] == '(') or (char == '}' and bracket_stack[-1] == '{')):
                bracket_stack.pop()
            current_value.append(char)
            continue
        
        # 当不在括号内且遇到冒号:确定键
        if char == ':' and not bracket_stack:
            current_key = ''.join(current_key).strip()
            current_value = []
            continue
        
        # 当不在括号内且遇到空格:完成一个键值对
        if char.isspace() and not bracket_stack:
            if current_key and current_value:
                pairs.append((current_key, ''.join(current_value).strip()))
                current_key = []
                current_value = []
            continue
        
        # 否则添加到当前内容
        if current_key:
            current_value.append(char)
        else:
            current_key.append(char)
    
    # 处理最后一个键值对
    if current_key and current_value:
        pairs.append((current_key, ''.join(current_value).strip()))
    
    return dict(pairs)

s = "p1: I/out   p2: (('mean', 5), 0.0, ('std', 2))   p3: 7   p4: {'name': 'check', 'value': 80.0}"
print(extract_key_value_pairs(s))

输出和方案1一致,这个方法不需要依赖第三方库,且能处理任意深度的嵌套括号。

原正则的问题说明

你之前用的[\s:]+(?=[^\{\(\)\}]*(?:[\{\(]|$)),其前瞻部分只检查到下一个括号或字符串结尾,但没有考虑括号的闭合。当遇到(('mean', 5), 0.0, ('std', 2))时,0.0前面的空格处于括号内部,但前瞻会误判为可以分割的位置,因为它只看到前面的),没意识到整个外层括号还没闭合。

内容的提问来源于stack exchange,提问作者olivaw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 17:30:44