[英]Python RegEx Discrepancy vs Kodos and RegExr: Can't Filter Specific Character in 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>
我的问题有两个:
澄清:对于那些问什么标准正则表达式的人-这是形式语言理论标准: 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实现建议了一些扩展(与大多数其他软件包一样)。
感谢您的回答。 我觉得每个答案都有一部分答案。 这是我一直在寻找的东西。
? 符号只是(something |ε)的简写。 因此(a |ε)可以改写为a? 。 因此,示例变为:
b*(abb*)*a?
在python中,我们将编写:
p = re.compile(r'^b*(abb*)*a?$')
将正则表达式语法直接转换为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.