我正在读一本书,他们提供了一个如何将给定字符串与正则表达式匹配的示例。 这是他们的例子:
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>
我的问题是双重的:
答案 0 :(得分: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
请注意,组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 :(得分:5)
感谢您的回答。我觉得每个答案都有答案的一部分。这就是我要找的东西。
?符号只是(某事|ε)的简写。因此,(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'
答案 2 :(得分:3)
1
使用bool(p.match('aa'))
检查正则表达式是否匹配
p = re.compile('b*(abb*)*a?$')
\b
匹配字符串的边框; \w
和\W
之间的位置(单词字符和非单词字符)
2
Regexp在python中非常标准。然而,每种语言都有一些风格,它们不是100%便携的。在使用任何特定语言的regexp之前,您需要查找的细微差别。
<强>加成强>
\epsilon
在python中没有特殊符号。这是一个空字符集。
在您的示例中,a|\epsilon
相当于(a|)
或a?
。之后$
必须匹配字符串的结尾。
答案 3 :(得分:3)
我不确定python中的匹配是如何工作的,但我认为您可能需要将^ .... $添加到您的RE中。 RegExp匹配通常匹配子字符串,并且它找到最大匹配,在p.match('aa')的情况下,它是“a”(可能是第一个)。 ^ ... $确保你匹配整个字符串,我相信你想要的。
理论/标准reg exps假设你总是匹配整个字符串,因为你用它来定义匹配的字符串语言,而不是在输入字符串中找到子字符串。
答案 4 :(得分:1)
您正在匹配,因为您的正则表达式匹配任何标本文本的任何零宽度段。你需要锚定你的正则表达式。这是使用零宽度前瞻断言的一种方法:
re.compile(r'^(a(?!a)|b)*$')
答案 5 :(得分:1)
尽管我以前从未在正则表达式中看过epsilon,但你的第二个应该是epsilon的合适替代品。
对于它的价值,你的模式匹配'a'。也就是说,它匹配:
b
”s(选择零)(abb*)
”s(选择零)a
”或单词结尾(选择a)。正如Jonathan Feinberg所指出的,如果你想确保整个字符串匹配,你必须锚定你的正则表达式的开头('^'
)和结束('$'
)。每当在python中构造正则表达式时,你也应该使用原始字符串:r'my regex'。这样可以防止过多的反斜杠逃避混乱。
答案 6 :(得分:1)
表达式的问题在于它与空字符串匹配,这意味着如果你这样做:
>>> 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-您可能已经注意到我在here(第一段)上使用了r'pattern'而不是'pattern'