正则表达式:如何使用正则表达式在可选捕获组之后捕获组?

时间:2013-11-28 15:18:52

标签: python regex string

假设我有以下字符串:

s1=u'--FE(-)---'
s2=u'--FEM(-)---'
s3=u'--FEE(--)-'

我想匹配F,E,E,M和不同组中括号的内容。

我尝试过以下正则表达式:

u'^.-([F])([EF]*)([E]+)[^FEM]?(M*)?(\\(.*\\))?.*$'

此表达式为不同的字符串提供以下组和跨度:

s1 -> 'F',(2,3)   ,   '',(3,3)    ,    'E',(3,4)    ,    '',(5,5)    ,    None,(-1,-1)
s2 -> 'F',(2,3)   ,   '',(3,3)    ,    'E',(3,4)    ,    'M',(4,5)   ,    (-),(5,8)
s3 -> 'F',(2,3)   ,   'E',(3,4)   ,    'E',(4,5)    ,    '',(6,6)    ,    None,(-1,-1)

对于s2,我得到了想要的行为,括号内容的匹配,但对于s1和s3,我没有。

如果我没有与包含'M'的组的正确匹配,我如何创建一个与括号内容匹配的正则表达式?

编辑:

DWilches的答案使用正则表达式

解决了初始问题
'^.-(F)([EF]*)(E+)[^FEM]??(M*)(\(.*\)).*?$'

但是,括号组也是可选的。以下简短的python脚本澄清了问题:

s1=u'--FE(-)---'
s2=u'--FEM(-)--'
s3=u'--FEE(--)-'
s4=u'--FEE-M(---)--'
s5=u'--FE-M-(-)-'
s6=u'--FEM--'
s7=u'--FE-M--'

ll=[s1,s2,s3,s4,s5,s6,s7]

import re
rr1=re.compile(u'^.-(F)([EF]*)(E+)[^FEM]??(M*)[^FEM]??(\(.*\)).*?$')
rr2=re.compile(u'^.-(F)([EF]*)(E+)[^FEM]??(M*)[^FEM]??(\(.*\))?.*?$')

for s in ll:
    b=rr1.search(s)
    print s
    if b:
        print " '%s' '%s' '%s' '%s' '%s' " % (b.group(1), b.group(2), b.group(3),     b.group(4), b.group(5))
    else:
        print 'No match'
    print '######'

对于rr1,输出为:

--FE(-)---
 'F' '' 'E' '' '(-)' 
######
--FEM(-)--
 'F' '' 'E' 'M' '(-)' 
######
--FEE(--)-
 'F' 'E' 'E' '' '(--)' 
######
--FEE-M(---)--
 'F' 'E' 'E' 'M' '(---)' 
######
--FE-M-(-)-
 'F' '' 'E' 'M' '(-)' 
######
--FEM--
No match
######
--FE-M--
No match
######

对于前5个字符串是可以的,但不是最后两个字符串,因为它需要括号。

然而,rr2?添加到(\(.*\))会产生以下输出:

--FE(-)---
 'F' '' 'E' '' '(-)' 
######
--FEM(-)--
 'F' '' 'E' 'M' '(-)' 
######
--FEE(--)-
 'F' 'E' 'E' '' '(--)' 
######
--FEE-M(---)--
 'F' 'E' 'E' '' 'None' 
######
--FE-M-(-)-
 'F' '' 'E' '' 'None' 
######
--FEM--
 'F' '' 'E' 'M' 'None' 
######
--FE-M--
 'F' '' 'E' '' 'None' 
######

这适用于s1,s2,s3s6

需要进行一些修改才能产生所需的输出:如果存在,则获取M;如果括号存在,则获取括号的内容。

1 个答案:

答案 0 :(得分:3)

您似乎需要使用非贪婪的运算符:

^.-(F)([EF]*)(E+)[^FEM]??(M*)(\\(.*\\))?.*?$

请注意,在最后一个.*我添加了?。我还为[^FEM]?更改了[^FEM]??

在您的第一个示例中,问题是最后.*正在吃掉这个:-)[^FEM]?正在吃掉它时:( ...因此不会为(\\(.*\\))?

留下任何东西

(我还删除了单个字母周围的一些方括号,但更多的是使用较短的正则表达式)

使用此正则表达式,我获得以下结果:

--FE(-)---    ->     'F'    ''     'E'    ''     '(-)'
--FEM(-)---   ->     'F'    ''     'E'    'M'    '(-)'
--FEE(--)-    ->     'F'    'E'    'E'    ''     '(--)'

顺便说一句:我还会删除?末尾的(\\(.*\\))?,因为即使你没有把它放在那里,下面也会使用与该部分不匹配的字符串.*?