python嵌套结构_用Python中的正则表达式匹配嵌套结构

编辑:falsetru's nested parser比我原来的解决方案更快、更简单,我稍微修改了一下,接受了指定分隔符和项分隔符的任意regex模式: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']

嵌套结构不能单独与Python regex匹配,但是使用re.Scanner构建一个基本解析器(它可以处理嵌套结构)非常容易:import re

class Node(list):

def __init__(self, parent=None):

self.parent = parent

class NestedParser(object):

def __init__(self, left='\(', right='\)'):

self.scanner = re.Scanner([

(left, self.left),

(right, self.right),

(r"\s+", None),

(".+?(?=(%s|%s|$))" % (right, left), self.other),

])

self.result = Node()

self.current = self.result

def parse(self, content):

self.scanner.scan(content)

return self.result

def left(self, scanner, token):

new = Node(self.current)

self.current.append(new)

self.current = new

def right(self, scanner, token):

self.current = self.current.parent

def other(self, scanner, token):

self.current.append(token.strip())

可以这样使用: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 examplep = 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('', '')

print(p.parse("BARBAZ"))

# [['BAR', ['BAZ']]]

当然,pyparsing比上面的代码能做的多得多。但就这个单一目的而言,上面的NestedParser对于小字符串来说大约快5倍: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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值