import re
def parse_nested(text, left=r'[(]', right=r'[)]', sep=r','):
""" https://stackoverflow.com/a/17141899/190597 (falsetru) """
pat = r'({}|{}|{})'.format(left, right, sep)
tokens = re.split(pat, text)
stack = [[]]
for x in tokens:
if not x or re.match(sep, x):
continue
if re.match(left, x):
# Nest a new list inside the current list
current = []
stack[-1].append(current)
stack.append(current)
elif re.match(right, x):
stack.pop()
if not stack:
raise ValueError('error: opening bracket is missing')
else:
stack[-1].append(x)
if len(stack) > 1:
print(stack)
raise ValueError('error: closing bracket is missing')
return stack.pop()
text = "a {{c1::group {{c2::containing::HINT}} a few}} {{c3::words}} or three"
print(parse_nested(text, r'\s*{{', r'}}\s*'))
收益率
['a', ['c1::group', ['c2::containing::HINT'], 'a few'], ['c3::words'], 'or three']
p = NestedParser()
print(p.parse("((a+b)*(c-d))"))
# [[['a+b'], '*', ['c-d']]]
p = NestedParser()
print(p.parse("( (a ( ( c ) b ) ) ( d ) e )"))
# [[['a', [['c'], 'b']], ['d'], 'e']]
默认情况下,NestedParser匹配嵌套括号。您可以传递其他正则表达式以匹配其他嵌套模式,如括号、[]。For example
p = NestedParser('\[', '\]')
result = (p.parse("Lorem ipsum dolor sit amet [@a xxx yyy [@b xxx yyy [@c xxx yyy]]] lorem ipsum sit amet"))
# ['Lorem ipsum dolor sit amet', ['@a xxx yyy', ['@b xxx yyy', ['@c xxx yyy']]],
# 'lorem ipsum sit amet']
p = NestedParser('<foo>', '</foo>')
print(p.parse("<foo>BAR<foo>BAZ</foo></foo>"))
# [['BAR', ['BAZ']]]
In [27]: import pyparsing as pp
In [28]: data = "( (a ( ( c ) b ) ) ( d ) e )"
In [32]: %timeit pp.nestedExpr().parseString(data).asList()
1000 loops, best of 3: 1.09 ms per loop
In [33]: %timeit NestedParser().parse(data)
1000 loops, best of 3: 234 us per loop
对于更大的字符串,大约快28倍:
In [44]: %timeit pp.nestedExpr().parseString('({})'.format(data*10000)).asList()
1 loops, best of 3: 8.27 s per loop
In [45]: %timeit NestedParser().parse('({})'.format(data*10000))
1 loops, best of 3: 297 ms per loop
通常不能使用Python正则表达式来实现这一点。(.NET正则表达式已扩展为“平衡组”,这就是允许嵌套匹配的原因。)
然而,PyParsing对于这类事情来说是一个非常好的包:
输出为:
有关PyParsing的详细信息:
编辑:falsetru's nested parser比我原来的解决方案更快、更简单,我稍微修改了一下,接受了指定分隔符和项分隔符的任意regex模式:
收益率
嵌套结构不能单独与Python regex匹配,但是使用re.Scanner构建一个基本解析器(它可以处理嵌套结构)非常容易:
可以这样使用:
默认情况下,
NestedParser
匹配嵌套括号。您可以传递其他正则表达式以匹配其他嵌套模式,如括号、[]
。For example当然,
pyparsing
比上面的代码能做的多得多。但就这个单一目的而言,上面的NestedParser
对于小字符串来说大约快5倍:对于更大的字符串,大约快28倍:
正则表达式不能分析嵌套结构。根据定义,嵌套结构不是正则的。它们不能由正则语法构造,也不能由有限状态自动机解析(正则表达式可以看作是FSA的简写符号)。
今天的“regex”引擎有时支持一些有限的“嵌套”结构,但从技术角度来看,它们不应该再被称为“常规”了。
相关问题 更多 >
编程相关推荐