python:re.search不是从字符串的开头开始的吗?

时间:2017-02-06 14:20:43

标签: python regex

我正在使用Flask API,它将以下正则表达式作为端点:

([0-9]*)((OK)|(BACK)|(X))* 

这意味着我会在数字之后连续多次预期一系列数字,以及OK,BACK,X关键字。

我想拆分这个正则表达式并根据哪些捕获组存在来做不同的事情。

我的方法如下:

endp = endp.encode('ASCII', 'ignore')
    match = re.search(r"([0-9]*)", str(endp), re.I)
    if match:
        n = match.groups()
        logging.info('nums: ' + str(n[0]))

    match = re.search(r"((OK)|(BACK)|(X))*", str(endp), re.I)
    if match:
        s1 = match.groups()
        for i in s1:
            logging.info('str: ' + str(i[0]))

使用/ 12OK端点,获取数字工作正常,但由于某些原因捕获其余关键字不成功。我尝试将第二个捕获组缩减为

match = re.search(r"(OK)*", str(endp), re.I)

我经常在s1中找到以下内容(使用简化的正则表达式):

(None,)

最初(使用其他关键字):

(None, None, None, None)

我认为这意味着正则表达式模式与我的endp字符串中的任何内容都不匹配(为什么它有4个Nones?每个关键字1个,但第4个是什么?)。我使用正则表达式验证器验证了我的端点(对同一个字符串的正则表达式),对我来说似乎很好。我知道re.match应该从头开始匹配,因此我使用re.search方法,因为documentation指出它应该匹配字符串中的任何位置。

我在这里缺少什么?请指教,我是蟒蛇世界的初学者。

4 个答案:

答案 0 :(得分:0)

如果您想要匹配至少一个群组,请使用+代替*

>>> endp = '/12OK'
>>> match = re.search(r"((OK)|(BACK)|(X))+", str(endp), re.I)
>>> if match:
...     s1 = match.groups()
...     for i in s1:
...         print s1
...
('OK', 'OK', None, None)
>>> endp = '/12X'
>>> match = re.search(r"((OK)|(BACK)|(X))+", str(endp), re.I)
>>> match.groups()
('X', None, None, 'X')

请注意,表达式中有4个匹配的组,每对括号一个。第一个匹配是外括号,第二个匹配是第一个嵌套组。在第二个例子中,你仍然得到外括号的第一个匹配,然后最后一个是嵌套的第三个匹配。

答案 1 :(得分:0)

"((OK)|(BACK)|(X))*"将搜索OK或BACK或X,0或更多次。请注意,*表示0或更多,不超过0.上面的表达式应该在结尾处+不*,+表示1或更多。

答案 2 :(得分:0)

确实用*搜索返回“无:

”有点令人惊讶
>>> re.search("(OK|BACK|X)*", u'/12OK').groups()
(None,)

但它是“正确的”,因为*匹配零或更多,并且任何模式在任何字符串中匹配零次,这就是您看到None的原因。用+搜索有点解决它:

>>> re.search("(OK|BACK|X)+", u'/12OK').groups()
('OK',)

但现在,在/12OKOK中使用此模式进行搜索仍然只找到一个匹配,因为+表示一个或多个,并且它在第一个OK匹配一次。要查找所有事件,您需要使用re.findall

>>> re.findall("(OK|BACK|X)", u'/12OKOK')
['OK', 'OK']

根据这些发现,您的代码将如下所示:(请注意,您不需要编写i[0],因为i已经是一个字符串,除非您只想记录第一个字符串字符串):

import re

endp = endp.encode('ASCII', 'ignore')
match = re.search(r"([0-9]+)", str(endp))
if match:
    n = match.groups()
    logging.info('nums: ' + str(n))

match = re.findall(r"(OK|BACK|X)", str(endp), re.I)
for i in match:
    logging.info('str: ' + str(i))

答案 3 :(得分:0)

我认为你有两个不同的问题,他们的交集导致了比他们自己造成的更多混乱。

第一个问题是您正在使用重复的组。 Python的re库在重复组时无法捕获多个匹配项。与(X)+类型的模式匹配'XXXX'将只捕获第一组中的单个'X',即使整个字符串将匹配。 regex library(不是标准库的一部分)可以进行多次捕获,但我不确定所需的确切命令。

第二个问题是在模式中使用*重复运算符。您在问题顶部显示的模式将匹配空字符串。显然,在这种情况下,没有一个gropus会捕获任何东西(这可能就是你在结果中看到很多None个条目的原因)。您可能需要修改模式,以便需要一些最小数量的有效文本作为匹配项。使用+代替*可能是一种解决方案,但我不清楚您想要匹配哪些内容,因此我无法建议特定的模式。