Python 在乱码字符串中匹配开括号和关括号

Python 在乱码字符串中匹配开括号和关括号,python,regex,Python,Regex,如何将一个随机字符串(包含各种字符)解析成连贯的东西 例如,string='{“字母”:“321”}{{}{{{}}}{{{}':“stack{}}{}{}}{}' 我想分为以下几个部分: {“字母”:“321”}{{}}和{}{{}}}:“stack{}}{}{} 我试着遍历字符串,计算每个打开的括号{,并在出现闭括号时进行减法。但是,这不起作用,因为有些实例中括号位于或内 我的代码大致如下: list1 = [] # list1 is where we build up the first

如何将一个随机字符串(包含各种字符)解析成连贯的东西

例如,
string='{“字母”:“321”}{{}{{{}}}{{{}':“stack{}}{}{}}{}'
我想分为以下几个部分:
{“字母”:“321”}{{}}
{}{{}}}:“stack{}}{}{}

我试着遍历
字符串
,计算每个打开的括号{,并在出现闭括号时进行减法。但是,这不起作用,因为有些实例中括号位于
内
我的代码大致如下:

list1 = []  # list1 is where we build up the first string
list2 = []  # list2 is where we keep the strings after building
for c in string:
    list1.append(c)
    if c == "{":
        bracket_counter += 1
    elif c == "}":
        bracket_counter -= 1
        if bracket_counter == 0:
            list2.append("".join(item)) 
            list1 = []
使用此代码,被视为“完整”的第一个字符串是
{“字母”:“321”}
,即使它应该是
{“字母”:“321”}{}

我对regex非常不熟悉,所以我不确定这是否是我应该使用它的原因。任何帮助都将不胜感激

谢谢!

您还必须检查您是否在字符串中。一种简单的方法是,如果您在字符串中且不是结束字符,则生成另一个变量并跳过循环

括号\u计数器=0
quote=“”
list1=[]#list1是我们构建第一个字符串的地方
list2=[]#list2是我们在构建后保留字符串的地方
对于字符串中的c:
清单1.追加(c)
如果不是引号或c==引号:#如果引号为空或找到结束引号
quote=“”
如果c==“{”:
括号+计数器+=1
elif c==“}”:
括号_计数器-=1
如果括号_计数器==0:
列表2.追加(“.join(项目))
列表1=[]
如果字符是引号字符,请在“\”中使用elif c:\
quote=c#将跳过循环,直到找到quote
如果您想要一个正则表达式,您首先会模仿:

{.*.}
但您希望忽略引号,因此您可以:

{((“*?”)|(“.*?”)|.*?}
基本上,这利用了惰性量词。它试图找到引用的东西,如“…”,然后“…”,最后选择任何字符

如果不想使用惰性量词,请使用正则表达式:

tokens = '(?:' + '|'.join([OPS, SQ, DQ, WS, NON_SPECIAL]) + ')'
{(“[^”]*”|'[^']*'|[^{}])*}
这给出了代码:

重新导入
def解析:
返回[group[0]对于re.findall中的组(({(\“*?\”)\124;('.*?')\ 124;)*?}),s)]
用法:

>>string=“{”字母“:'321”}{{{}{{}}}{{}}':“stack{}}{}{}”
>>>解析(字符串)
[“{”字母“:'321”}{{}},'{}{{}}{}}\':“stack{}{}}{}']
>>>打印(“,”.join(解析(字符串)))
{“字母”:“321”}{{}},{{{}{}}:“堆栈{}}{}”

您可以使用正则表达式标记字符串,然后迭代这些标记。例如:

SQ = r"'[^']*'"   # single-quoted string
DQ = r'"[^"]*"'   # double-quoted string
OPS = r'[{}:]'    # operators
WS = r'\s+'       # whitespace
     # add more types as needed...
tokens = '(?:' + '|'.join([OPS, SQ, DQ, WS]) + ')'
pattern = re.compile(tokens, re.DOTALL)

def tokenize(source):
    start = 0
    end = len(source)
    while start < end:
        match = pattern.match(source, start)
        if match:
            yield match.group(0)
        else:
            raise ValueError('Invalid syntax at character %d' % start)

        start = match.end()
示例输入中的标记为:

>>> for token in tokenize(string):
...     print(token)
'{'
'"letters"'
' '
':'
' '
'\'321"}{}"\''
'}'
'{'
'\'{}{{}"\''
':'
' '
'"stack{}}{"'
'}'
正如您所看到的,从这里您可以正确地计算
'{'
'}'


请注意,上面的正则表达式没有转义字符串中的
'
的概念;如果希望
\
转义结束字母,并且它正确地标记了,可以将
SQ
DQ
正则表达式更改为

SQ = r"'(?:[^\\']|\\.)*'"
DQ = r'"(?:[^\\"]|\\.)*"'
此外,如果您希望允许任何其他字符,但不需要特别处理,则可以添加

NON_SPECIAL = r'[^\'"]'
作为正则表达式的最后一个分支:

tokens = '(?:' + '|'.join([OPS, SQ, DQ, WS, NON_SPECIAL]) + ')'

正则表达式对于解析来说是一个糟糕的选择,这正是您需要在这里做的。您意识到您的括号是不平衡的,对吗?这并不是正则表达式所能做到的,更重要的是,人类无法看到它,也无法辨别任何东西……您不会使用正则表达式,而是使用许多正则表达式来匹配输入中的标记,然后使用解析器来构建在这个例子中,你的分离似乎没有遵循任何明显的逻辑。你需要进一步解释为什么你在那个时候分离。