2010-11-26 152 views
11

显然,这个问题出现了相当频繁,读解析在python嵌套的括号,按级别抢内容

Regular expression to detect semi-colon terminated C++ for & while loops

和思考一会儿这个问题后,我写了一个函数返回所包含的内容内嵌任意数量的嵌套()

该函数可以很容易地扩展到任何正则表达式对象,在这里发表您的想法和注意事项。

任何重构的建议,将不胜感激

(注意,我是新来的蟒蛇还在,并没有觉得自己搞清楚如何引发异常或什么的,所以我只是有函数返回“失败”如果couldin't弄清楚发生了什么事情)

编辑功能考虑到的意见:

def ParseNestedParen(string, level): 
    """ 
    Return string contained in nested(), indexing i = level 
    """ 
    CountLeft = len(re.findall("\(", string)) 
    CountRight = len(re.findall("\)", string)) 
    if CountLeft == CountRight: 
     LeftRightIndex = [x for x in zip(
     [Left.start()+1 for Left in re.finditer('\(', string)], 
     reversed([Right.start() for Right in re.finditer('\)', string)]))] 

    elif CountLeft > CountRight: 
     return ParseNestedParen(string + ')', level) 

    elif CountLeft < CountRight: 
     return ParseNestedParen('(' + string, level) 

    return string[LeftRightIndex[level][0]:LeftRightIndex[level][1]] 

回答

23

你不说清楚你的函数的规范是什么,但这种行为似乎是错误的我:

>>> ParseNestedParen('(a)(b)(c)', 0) 
['a)(b)(c'] 
>>> nested_paren.ParseNestedParen('(a)(b)(c)', 1) 
['b'] 
>>> nested_paren.ParseNestedParen('(a)(b)(c)', 2) 
[''] 

对您的代码的其他评论:

  • Docstring说“生成”,但函数返回一个列表,而不是生成器。
  • 由于只返回一个字符串,为什么返回列表?
  • 在什么情况下函数可以返回字符串fail
  • 反复致电re.findall,然后扔掉结果是浪费。
  • 您尝试重新平衡字符串中的括号,但您一次这样做只有一个括号:
>>> ParseNestedParen(')' * 1000, 1) 
RuntimeError: maximum recursion depth exceeded while calling a Python object 

由于Thomi在question you linked to说,“正则表达式真的是错误的工具!“


通常的方法来解析嵌套表达式是使用堆栈,沿着这些线路:

def parenthetic_contents(string): 
    """Generate parenthesized contents in string as pairs (level, contents).""" 
    stack = [] 
    for i, c in enumerate(string): 
     if c == '(': 
      stack.append(i) 
     elif c == ')' and stack: 
      start = stack.pop() 
      yield (len(stack), string[start + 1: i]) 

>>> list(parenthetic_contents('(a(b(c)(d)e)(f)g)')) 
[(2, 'c'), (2, 'd'), (1, 'b(c)(d)e'), (1, 'f'), (0, 'a(b(c)(d)e)(f)g')] 
+0

与 相关的行为ParseNestedParen('(a)(b)(c)',0) 实际上是正确的,但我的功能是工作的错误工具,我用 写了函数string =“some_function another_function(some_argument))“ 记住。 为什么返回列表?不应该有。好点,谢谢! 什么时候我会返回失败?我不知道。也许永远不会它从那里我编码功能 repairedly调用查找所有是浪费?因此,我应该在[“\(”,“\)”]] 中使用列表 countparen = [re.findall(str)for str并使用它? 我该如何重新理解括号? 感谢您的意见! – 2010-11-26 12:18:40

0
#!/usr/bin/env python 
import re 

def ParseNestedParen(string, level): 
    """ 
    Generate strings contained in nested(), indexing i = level 
    """ 
    if len(re.findall("\(", string)) == len(re.findall("\)", string)): 
     LeftRightIndex = [x for x in zip(
     [Left.start()+1 for Left in re.finditer('\(', string)], 
     reversed([Right.start() for Right in re.finditer('\)', string)]))] 

    elif len(re.findall("\(", string)) > len(re.findall("\)", string)): 
     return ParseNestedParen(string + ')', level) 

    elif len(re.findall("\(", string)) < len(re.findall("\)", string)): 
     return ParseNestedParen('(' + string, level) 

    else: 
     return 'fail' 

    return [string[LeftRightIndex[level][0]:LeftRightIndex[level][1]]] 

测试:

if __name__ == '__main__': 

    teststring = "outer(first(second(third)second)first)outer" 

    print(ParseNestedParen(teststring, 0)) 
    print(ParseNestedParen(teststring, 1)) 
    print(ParseNestedParen(teststring, 2)) 

    teststring_2 = "outer(first(second(third)second)" 

    print(ParseNestedParen(teststring_2, 0)) 
    print(ParseNestedParen(teststring_2, 1)) 
    print(ParseNestedParen(teststring_2, 2)) 

    teststring_3 = "second(third)second)first)outer" 

    print(ParseNestedParen(teststring_3, 0)) 
    print(ParseNestedParen(teststring_3, 1)) 
    print(ParseNestedParen(teststring_3, 2)) 

输出:

Running tool: python3.1 

['first(second(third)second)first'] 
['second(third)second'] 
['third'] 
['first(second(third)second)'] 
['second(third)second'] 
['third'] 
['(second(third)second)first'] 
['second(third)second'] 
['third'] 
>>> 
+0

所以,你可以告诉,该功能允许不平衡括号,虽然不是一个非常优雅的方式。 – 2010-11-26 11:54:28