有时我们需要匹配像( 100 * ( 50 + 15 ) )这样的可嵌套的层次性结构,这时简单地使用\(.+\)则只会匹配到最左边的左括号和最右边的右括号之间的内容(这里我们讨论的是贪婪模式,懒惰模式也有下面的问题)。假如原来的字符串里的左括号和右括号出现的次数不相等,比如( 5 / ( 3 + 2 ) ) ),那我们的匹配结果里两者的个数也不会相等。有没有办法在这样的字符串里匹配到最长的,配对的括号之间的内容呢? ”
在.Net Framework的正则表达式中,提供了”平衡组/递归匹配“的处理方法(见《 正则表达式30分钟入门教程》)。
在python中,又有什么方法较好的实现这种匹配呢?
9 个解决方案
#1
这已经不是正则表达式了,是context free grammar。你可以自己写一个parser,或者用PLY之类的工具生成一个parser。
#2
建议读一下“Python正则表达式操作指南”http://www.cnblogs.com/babykick/archive/2011/03/30/1999428.html
#3
正则表达式没法完成,写个递归函数从最外面,到最里面,直到找不到'('为止。
#4
def matchlp(s):
spos = [];
rs = "";
for i in range(0, len(s)):
if(s[i] == '('):
spos.append(i);
continue;
if(s[i] == ')' and spos):
ts = s[spos[-1]: i+1];
if(len(ts) > len(rs)):
rs = ts;
spos.pop();
return rs;
s = " 5 / ( 3 + 2 ) ) ),";
rs = matchlp(s);
print(rs);
#5
to 1#:
太复杂了,我有心无力
to 2#:
读完就能够回答楼主位的问题了吗?
to 3#:
是个办法,4#给出了具体实现
to 4#:
贴个友坛上的回复,相互学习:
太复杂了,我有心无力
to 2#:
读完就能够回答楼主位的问题了吗?
to 3#:
是个办法,4#给出了具体实现
to 4#:
贴个友坛上的回复,相互学习:
import re
pattern_0 = r'\([^()]*\)' #depth 0 pattern
pat_left = r'\((?:[^()]|'
pat_right = r')*\)'
def pattern_generate(pattern, depth=0):
while(depth):
pattern = pat_left + pattern + pat_right
depth -= 1
return pattern
def main():
data = r'test(1+2*(2-1)-3*(5+2)+10+(()))'
pat = pattern_generate(pattern_0, 2)
print('Pattern:', pat)
prog = re.compile(pat)
result = prog.search(data)
if result:
print('Find: {}'.format(result.group(0)))
else:
print('Can\'t match')
if __name__ == '__main__':
main()
#6
4L不是3L实现,3L只能找到最深嵌套,最深不代表最长
5L也有问题, data = r'test(10000+1)(2000000+2)'; 找到的是(10000)+1
5L也有问题, data = r'test(10000+1)(2000000+2)'; 找到的是(10000)+1
#7
(10000+1)
#8
你是对的。
这是一个很复杂的问题,通过编程实现灵活性又差了很多。现在再看看,似乎1#的才是终极方案啊。
#9
那讨论的最终结果呢。 怎么没人粘出来。。。
#1
这已经不是正则表达式了,是context free grammar。你可以自己写一个parser,或者用PLY之类的工具生成一个parser。
#2
建议读一下“Python正则表达式操作指南”http://www.cnblogs.com/babykick/archive/2011/03/30/1999428.html
#3
正则表达式没法完成,写个递归函数从最外面,到最里面,直到找不到'('为止。
#4
def matchlp(s):
spos = [];
rs = "";
for i in range(0, len(s)):
if(s[i] == '('):
spos.append(i);
continue;
if(s[i] == ')' and spos):
ts = s[spos[-1]: i+1];
if(len(ts) > len(rs)):
rs = ts;
spos.pop();
return rs;
s = " 5 / ( 3 + 2 ) ) ),";
rs = matchlp(s);
print(rs);
#5
to 1#:
太复杂了,我有心无力
to 2#:
读完就能够回答楼主位的问题了吗?
to 3#:
是个办法,4#给出了具体实现
to 4#:
贴个友坛上的回复,相互学习:
太复杂了,我有心无力
to 2#:
读完就能够回答楼主位的问题了吗?
to 3#:
是个办法,4#给出了具体实现
to 4#:
贴个友坛上的回复,相互学习:
import re
pattern_0 = r'\([^()]*\)' #depth 0 pattern
pat_left = r'\((?:[^()]|'
pat_right = r')*\)'
def pattern_generate(pattern, depth=0):
while(depth):
pattern = pat_left + pattern + pat_right
depth -= 1
return pattern
def main():
data = r'test(1+2*(2-1)-3*(5+2)+10+(()))'
pat = pattern_generate(pattern_0, 2)
print('Pattern:', pat)
prog = re.compile(pat)
result = prog.search(data)
if result:
print('Find: {}'.format(result.group(0)))
else:
print('Can\'t match')
if __name__ == '__main__':
main()
#6
4L不是3L实现,3L只能找到最深嵌套,最深不代表最长
5L也有问题, data = r'test(10000+1)(2000000+2)'; 找到的是(10000)+1
5L也有问题, data = r'test(10000+1)(2000000+2)'; 找到的是(10000)+1
#7
(10000+1)
#8
你是对的。
这是一个很复杂的问题,通过编程实现灵活性又差了很多。现在再看看,似乎1#的才是终极方案啊。
#9
那讨论的最终结果呢。 怎么没人粘出来。。。