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