繁体   English   中英

标准正则表达式与python正则表达式之间的差异

[英]Standard Regex vs python regex discrepancy

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

b*(abb*)*(a|∊) - Strings of a's and b's with no consecutive a's.

现在,我尝试将其转换为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>

我的问题有两个:

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

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

实际上,该示例工作得很好……只是一个很小的细节。 我会写:

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

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

如您所见,该表达式匹配连续的a和b,而不重复a。 如果确实要检查整个字符串,则需要稍作更改:

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

^$强制识别字符串的开头和结尾。

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

>>> len(m.group(0)) == len('aa')

补充:对于OT的第二部分,在我看来,标准正则表达式与python实现之间没有差异。 当然,表示法略有不同,并且python实现建议了一些扩展(与大多数其他软件包一样)。

感谢您的回答。 我觉得每个答案都有一部分答案。 这是我一直在寻找的东西。

  1. 符号只是(something |ε)的简写。 因此(a |ε)可以改写为a? 因此,示例变为:

     b*(abb*)*a? 

    在python中,我们将编写:

     p = re.compile(r'^b*(abb*)*a?$') 
  2. 将正则表达式语法直接转换为python(即复制和粘贴)不起作用的原因是,因为python匹配最短的子字符串 (如果没有$或^符号),而理论上的正则表达式匹配最长的初始子字符串
    例如,如果我们有一个字符串:

     s = 'aa' 

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

     >> p = re.compile(r'b*(abb*)*a?') >> bool(p.match(s)) True 

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

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

    请注意,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' 

1个

  • 使用bool(p.match('aa'))检查正则表达式是否匹配

  • p = re.compile('b*(abb*)*a?$')

  • \\b匹配字符串的边框; \\w\\W之间的位置(单词字符和非单词字符)

2

正则表达式在python中是非常标准的。 但是每种语言都有它们的风格,它们不是100%可移植的。 在使用任何特定语言的regexp之前,您应该先查找一些细微的差异。

加成

\\epsilon在python中没有特殊符号。 它是一个空字符集。

在您的示例中a|\\epsilon等效于(a|)或只是a? 之后, $必须匹配字符串的结尾。

我不完全确定match如何在python中工作,但我认为您可能需要在您的RE中添加^ .... $。 RegExp匹配通常匹配子字符串,并且在p.match('aa')为“ a”(可能是第一个)的情况下找到最大的匹配项。 ^ ... $确保您匹配整个字符串,我相信这是您想要的。

理论/标准正则表达式假定您始终匹配整个字符串,因为您使用它来定义匹配的字符串语言,而不是在输入字符串中找到子字符串。

之所以匹配,是因为您的正则表达式匹配任何标本文本的任何零宽度段。 您需要锚定正则表达式。 这是一种使用零宽度超前断言的方法:

re.compile(r'^(a(?!a)|b)*$')

据我所知,您的第二个回答应该是epsilon的合适替代品,尽管我以前从未在正则表达式中见过epsilon。

无论值多少,您的模式都匹配“ a”。 也就是说,它是匹配的:

  • 零个或多个“ b ”(选择零)
  • 零个或多个“ (abb*) ”(选择零)
  • 一个“ a ”或单词结尾(选择a)。

正如乔纳森·费恩伯格(Jonathan Feinberg)指出的那样,如果要确保整个字符串匹配,则必须锚定正则表达式的开头( '^' )和结尾( '$' )。 每当在python中构造正则表达式时,也应使用原始字符串:r'my regex'。 这样可以防止过多的反斜杠避免混淆。

表达式的问题在于它与空字符串匹配,这意味着如果您这样做:

>>> p = re.compile('b*(abb*)*(a|)')
>>> p.match('c').group(0)
''

并且由于re.match尝试匹配字符串的开头,因此您必须告诉它匹配它直到字符串的结尾。 只需使用$

>>> p = re.compile(r'b*(abb*)*(a|)$')
>>> print p.match('c')
None
>>> p.match('ababababab').group(0)
'ababababab'

ps-您可能已经注意到,我在此处更多使用r'pattern'而不​​是'pattern'(第一段)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM