标准正则表达式与python正则表达式差异

And*_*yuk 5 python regex theory

我正在读一本书,他们提供了一个如何将给定字符串与正则表达式匹配的示例.这是他们的例子:

b*(abb*)*(a|?) - Strings of a's and b's with no consecutive a's.
Run Code Online (Sandbox Code Playgroud)

现在我尝试将它转换为python,如下所示:

>> p = re.compile(r'b*(abb*)*(a|)') # OR
>> p = re.compile(r'b*(abb*)*(a|\b)')

# BUT it still doesn't work
>>> p.match('aa')
<_sre.SRE_Match object at 0x7fd9ad028c68>
Run Code Online (Sandbox Code Playgroud)

我的问题是双重的:

  1. 为了使上面的例子有效,python中的epsilon相当于什么?
  2. 有人可以向我解释为什么理论或标准的正则表达式方法在python中不起作用?它可能与最长匹配和最短匹配有关吗?

澄清:对于人们询问标准正则表达式是什么 - 它是形式语言理论标准:http://en.wikipedia.org/wiki/Regular_expression#Formal_language_theory

Pie*_*BdR 5

实际上,这个例子对于一个小细节来说效果很好.我会写:

>>> p = re.compile('b*(abb*)*a?')
>>> m = p.match('aa')
>>> print m.group(0)
'a'
>>> m = p.match('abbabbabababbabbbbbaaaaa')
>>> print m.group(0)
abbabbabababbabbbbba
Run Code Online (Sandbox Code Playgroud)

请注意,组0返回正则表达式匹配的字符串部分.

正如您所看到的,表达式匹配a和b的连续而不重复a.如果确实想要检查整个字符串,则需要稍微更改:

>>> p = re.compile('^b*(abb*)*a?$')
>>> m = p.match('aa')
>>> print m
None
Run Code Online (Sandbox Code Playgroud)

^$力识别字符串的开头和结尾的.

最后,您可以使用第一个正则表达式组合这两种方法,但最后测试:

>>> len(m.group(0)) == len('aa')
Run Code Online (Sandbox Code Playgroud)

补充:对于OT的第二部分,在我看来标准正则表达式和python实现之间没有差异.当然,符号略有不同,python实现提出了一些扩展(与大多数其他包一样).


And*_*yuk 5

谢谢你的回答.我觉得每个答案都有答案的一部分.这就是我要找的东西.

  1. 符号只是(某事|ε)的简写.因此(a |ε)可以重写为.所以这个例子变成了:

    b*(abb*)*a?
    
    Run Code Online (Sandbox Code Playgroud)

    在python中我们会写:

    p = re.compile(r'^b*(abb*)*a?$')
    
    Run Code Online (Sandbox Code Playgroud)
  2. 正规正则表达式语法的原因,直译成蟒(即复制和粘贴)不工作是因为蟒蛇匹配的最短子串(如果符号$ ^或不存在),而理论的正则表达式匹配最长的初始子.
    例如,如果我们有一个字符串:

    s = 'aa'
    
    Run Code Online (Sandbox Code Playgroud)

    我们的教科书正则表达式b*(abb*)*a?不会匹配它,因为它有两个a.但是如果我们直接将它复制到python:

    >> p = re.compile(r'b*(abb*)*a?')
    >> bool(p.match(s))
    True
    
    Run Code Online (Sandbox Code Playgroud)

    这是因为我们的正则表达式只匹配字符串'aa'的子字符串'a'.
    为了告诉python在整个字符串上进行匹配,我们必须分别用^$符号告诉它字符串的开头和结尾:

    >> p = re.compile(r'^b*(abb*)*a?$')
    >> bool(p.match(s))
    False
    
    Run Code Online (Sandbox Code Playgroud)

    请注意,python regex match()匹配字符串的开头,因此它会在开始时自动采用^.然而,search()函数没有,因此我们保持^.
    例如:

    >> s = 'aa'
    >> p = re.compile(r'b*(abb*)*a?$')
    >> bool(p.match(s))
    False                 # Correct
    >> bool(p.search(s))
    True                  # Incorrect - search ignored the first 'a'
    
    Run Code Online (Sandbox Code Playgroud)