Python:如何用正则匹配嵌套括号?
我正在尝试匹配一个像数学表达式一样的字符串,这个字符串里面有嵌套的括号。
import re
p = re.compile('\(.+\)')
str = '(((1+0)+1)+1)'
print p.findall(s)
['(((1+0)+1)+1)']
我希望它能匹配所有被括号包围的表达式,比如 (1+0)、((1+0)+1) 等等...
我甚至不在乎它是否会匹配到一些不想要的,比如 (((1+0),这些我可以自己处理。
为什么它现在没有做到这一点,我该怎么做呢?
12 个回答
25
现在有一个新的正则表达式引擎模块正在准备中,目的是要替换掉Python里现有的那个。这个新模块带来了很多新功能,其中包括递归调用。
import regex
s = 'aaa(((1+0)+1)+1)bbb'
result = regex.search(r'''
(?<rec> #capturing group rec
\( #open parenthesis
(?: #non-capturing group
[^()]++ #anyting but parenthesis one or more times without backtracking
| #or
(?&rec) #recursive substitute of group rec
)*
\) #close parenthesis
)
''',s,flags=regex.VERBOSE)
print(result.captures('rec'))
输出结果:
['(1+0)', '((1+0)+1)', '(((1+0)+1)+1)']
与regex
相关的bug:http://code.google.com/p/mrab-regex-hg/issues/detail?id=78
30
正如其他人提到的,正则表达式并不适合处理嵌套结构。我会用一个简单的例子来说明,使用的是pyparsing这个库:
import pyparsing # make sure you have this installed
thecontent = pyparsing.Word(pyparsing.alphanums) | '+' | '-'
parens = pyparsing.nestedExpr( '(', ')', content=thecontent)
下面是一个使用示例:
>>> parens.parseString("((a + b) + c)")
输出结果:
( # all of str
[
( # ((a + b) + c)
[
( # (a + b)
['a', '+', 'b'], {}
), # (a + b) [closed]
'+',
'c'
], {}
) # ((a + b) + c) [closed]
], {}
) # all of str [closed]
(这里的换行、缩进和注释都是手动处理的)
如果想要输出成嵌套列表的格式:
res = parens.parseString("((12 + 2) + 3)")
res.asList()
输出结果:
[[['12', '+', '2'], '+', '3']]
12
这个正则表达式会尽量匹配尽可能多的文本,所以它会把你整个字符串都用上。它不会在字符串的某些部分再寻找其他匹配的内容。这就是为什么你只得到一个结果的原因。
解决办法是不要使用正则表达式。如果你真的想解析数学表达式,应该使用专门的解析工具。如果你只是想提取括号里的内容,可以通过循环遍历字符,看到“(”就加一,看到“)”就减一,来计数。