从字符串中获取正确的大括号分组

时间:2016-07-21 07:16:00

标签: python

我的文件包含不正确的JSON,我想通过将其放入正确分组的块来开始修复。

大括号分组{{ {} {} } } {{}} {{{}}}应该已经是正确的

如何将所有顶级括号(正确分组)作为单独的字符串抓取?

3 个答案:

答案 0 :(得分:2)

如果你不想安装任何额外的模块,简单的功能就是:

def top_level(s):
    depth = 0
    start = -1

    for i, c in enumerate(s):
        if c == '{':
            if depth == 0:
                start = i
            depth += 1
        elif c == '}' and depth:
            depth -= 1
            if depth == 0:
                yield s[start:i+1]

print(list(top_level('{{ {} {} } } {{}} {{{}}}')))

输出:

['{{ {} {} } }', '{{}}', '{{{}}}']

它会跳过无效的大括号,但可以轻松修改,以便在发现错误时报告错误。

答案 1 :(得分:1)

使用regex module

In [1]: import regex

In [2]: braces = regex.compile(r"\{(?:[^{}]++|(?R))*\}")

In [3]: braces.findall("{{ {} {} } } {{}} {{{}}}")
Out[3]: ['{{ {} {} } }', '{{}}', '{{{}}}']

答案 2 :(得分:1)

pyparsing在这里真的很有帮助。它会处理你在字符串里面有大括号等的病态案例。自己完成所有这些工作可能有点棘手,幸运的是,某人(图书馆的作者)已经完成了hard stuff for us...。我将在这里重现代码以防止链接腐烂:

# jsonParser.py
#
# Implementation of a simple JSON parser, returning a hierarchical
# ParseResults object support both list- and dict-style data access.
#
# Copyright 2006, by Paul McGuire
#
# Updated 8 Jan 2007 - fixed dict grouping bug, and made elements and
#   members optional in array and object collections
#
json_bnf = """
object
    { members }
    {}
members
    string : value
    members , string : value
array
    [ elements ]
    []
elements
    value
    elements , value
value
    string
    number
    object
    array
    true
    false
    null
"""
from pyparsing import *

TRUE = Keyword("true").setParseAction( replaceWith(True) )
FALSE = Keyword("false").setParseAction( replaceWith(False) )
NULL = Keyword("null").setParseAction( replaceWith(None) )

jsonString = dblQuotedString.setParseAction( removeQuotes )
jsonNumber = Combine( Optional('-') + ( '0' | Word('123456789',nums) ) +
                    Optional( '.' + Word(nums) ) +
                    Optional( Word('eE',exact=1) + Word(nums+'+-',nums) ) )

jsonObject = Forward()
jsonValue = Forward()
jsonElements = delimitedList( jsonValue )
jsonArray = Group(Suppress('[') + Optional(jsonElements) + Suppress(']') )
jsonValue << ( jsonString | jsonNumber | Group(jsonObject)  | jsonArray | TRUE | FALSE | NULL )
memberDef = Group( jsonString + Suppress(':') + jsonValue )
jsonMembers = delimitedList( memberDef )
jsonObject << Dict( Suppress('{') + Optional(jsonMembers) + Suppress('}') )

jsonComment = cppStyleComment
jsonObject.ignore( jsonComment )

def convertNumbers(s,l,toks):
    n = toks[0]
    try:
        return int(n)
    except ValueError, ve:
        return float(n)

jsonNumber.setParseAction( convertNumbers )

唷!那是很多......现在我们如何使用它?这里的一般策略是扫描字符串中的匹配项,然后将这些匹配项从原始字符串中切片。每个扫描结果都是(lex-tokens, start_index, stop_index)形式的元组。对于我们的使用,我们不关心lex-tokens,只关注开始和停止。我们可以这样做:string[result[1], result[2]]它会起作用。我们也可以string[slice(*result[1:])] - 选择。

results = jsonObject.scanString(testdata)
for result in results:
    print '*' * 80
    print testdata[slice(*result[1:])]