簡體   English   中英

python:re.search不是從字符串開頭開始嗎?

[英]python: re.search doesn't start at beginning of string?

我正在開發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個None?每個關鍵字1個,但是第4個是什么呢?)。 我使用正則表達式驗證器驗證了端點(也針對同一字符串的正則表達式),這對我來說似乎很好。 我知道re.match應該從一開始就獲得匹配,因此我使用了re.search方法,因為文檔指出它應該與字符串中的任何地方匹配。

我在這里想念什么? 請告知,我是python世界的新手。

如果要匹配至少一個組,請使用+代替*

>>> 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個匹配的組,每對括號一個。 第一個匹配項是外部括號,第二個匹配項是嵌套組中的第一個。 在第二個示例中,您仍然會獲得外括號的第一個匹配項,然后最后一個是嵌套的第三個匹配項。

“(((OK)|(BACK)|(X))*”)將搜索OK或BACK或X,0次或更多次。 請注意,*表示0或更大,不超過0。上面的表達式的末尾應帶有+,而不是*,因為+表示1或更大。

確實,使用*搜索返回`None有點令人驚訝:

>>> 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已經是一個字符串,所以您無需編寫i[0] ,除非您只想記錄字符串的第一個字符):

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))

我認為您遇到了兩個不同的問題,它們的交集比任何一個單獨導致的混亂都多。

第一個問題是您正在使用重復的組。 當重復一個組時,Python的re庫無法捕獲多個匹配項。 (X)+類的模式對'XXXX'進行匹配,即使整個字符串都將被匹配,也只會在第一組中捕獲單個'X' regex (不是標准庫的一部分)可以執行多個捕獲,盡管我不確定所需的確切命令。

第二個問題是在模式中使用*重復運算符。 您在問題頂部顯示的模式將與空字符串匹配。 顯然,在這種情況下,沒有一個人能夠捕獲任何東西(這可能就是為什么您在結果中看到很多None條目的原因)。 您可能需要修改模式,以便它需要最少的有效文本才能算作匹配項。 使用+代替*可能是一種解決方案,但是我不清楚您要匹配的對象是什么,因此我無法建議特定的模式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM