2013-02-28 65 views
0

我想從字符串中提取一些字段,但是我不確定它們有多少個字段。 但是,我使用正則表達式,有一些我不明白的問題。python re matches groups

例如:

199 -> (199) 
    199,200 -> (199,200) 
    300,20,500 -> (300,20, 500) 

我試了一下,但是有些我不能得到這個工作。 希望任何人都可以給我一些建議。我會感激。

的正則表達式我想:

>>> re.match('^(\d+,)*(\d+)$', '20,59,199,300').groups() 
('199,', '300') 
// in this, I do not really care about ',' since I could use .strip(',') to trim that. 

我做了一些谷歌:並試圖re.findall使用,但我不知道我怎麼得到這個:

>>> re.findall('^(\d+,)*(\d+)$', '20,59,199,300') 
[('199,', '300')] 

--- -------------------------------------------------- - 更新

我意識到沒有講完整個故事,這個問題可能會讓人困惑。 基本上我想驗證在crontab(或類似的)中定義的語法

我爲_VALID_EXPRESSION創建一個數組:它是一個嵌套元組。

(field_1, 
    field_2, 
) 

每個field_1,它有兩個元,

field_1: ((0,59),  (r'....', r'....')) 
      valid_value valid_format 
在我的代碼

,它看起來像這樣:

_VALID_EXPRESSION = \ 
12  (((0, 59), (r'^\*$', r'^\*/(\d+)$', r'^(\d+)-(\d+)$', 
13     r'^(\d+)-(\d+)/(\d+)$', r'^(\d+,)*(\d+)$')), # second 
14  ((0, 59), (r'^\*$', r'^\*\/(\d+)$', r'^(\d+)-(\d+)$', 
15     r'^(\d+)-(\d+)/(\d+)$', r'^(\d+,)*(\d+)$')), # minute 
16  ....) 
在我的解析函數

,所有我需要做的就是隻需提取所有組,看看它們是否在有效值內。

我需要的正則表達式之一是它能夠正確匹配這個字符串'50,200,300',並在這種情況下提取所有數字。 (當然我可以使用split(),但是,它會背叛我的初衷,所以我不喜歡這個主意。)

希望這會有所幫助。

+0

告訴我們你試過的東西。除了這個事實,它使答覆者認爲你正在努力工作,而不僅僅是尋找解決方案,它還讓我們告訴你你錯了什麼,找到符合你理解的答案等。 – abarnert 2013-02-28 18:32:15

+0

在你的問題,你已經有'199'或'199,200'或'300,20,500'全部標記爲一段代碼。這是實際的源字符串,還是「199,200」?如果是後者...你爲什麼要匹配任何東西?如果你只是想匹配整個事情,你不需要正則表達式... – abarnert 2013-02-28 18:41:34

+0

你的問題仍然是模糊的。你想在第二個例子中使用字符串「(199,200)」嗎?如果是這樣,只是'({}).format(s)'有什麼問題?那麼你在談論的其他規則是什麼,它們不能像這些一樣被分割(',')? – abarnert 2013-02-28 18:46:10

回答

1

用正則表達式最簡單的辦法是這樣的:

r"(\d+,?)" 

您可以使用findall得到300,20,,以及您希望500。或者,如果你不希望逗號:

r"(\d+),?" 

此相匹配的組的1個或多個數字,其次是0或1逗號(組沒有)。

無論哪種方式:

>>> s = '300,20,500' 
>>> r = re.compile(r"(\d+),?") 
>>> r.findall(s) 
['300', '20', '500'] 

然而,由於薩赫勒格羅弗指出,如果這些是你輸入的字符串,這相當於只調用s.split(',')。如果您的輸入字符串可能有非數字,那麼這將確保您只匹配數字字符串,但即使這樣可能會更簡單,因爲filter(str.isdigit, s.split(','))

如果你想inttuple A S代替strlist S:

>>> tuple(map(int, r.findall(s))) 
(300, 20, 500) 

如果您發現推導/發電機表達式更容易比map/filter電話爲:

>>> tuple(int(x) for x in r.findall(s)) 
(300, 20, 500) 

或者,更簡單地說:

>>> tuple(int(x) for x in s.split(',') if x.isdigit()) 
(300, 20, 500) 

如果你想字符串(300, 20, 500),而你當然可以做到這一點只是對tuple調用repr,還有一個更簡單的方法來獲取:

>>> '(' + s + ')' 
'(300, 20, 500)' 

你原來的正則表達式:

'^(\d+,)*(\d+)$' 

...準備返回兩組,因爲您在模式中只有兩組。而且,由於您明確地將其包裝在^$中,因此它必須匹配整個字符串,因此findall在這裏不會幫助您 - 它會找到與match完全相同的一組(兩個組)。

3

爲什麼不直接使用string.split?

numbers = targetstr.split(',') 
+0

這有什麼用?這會給你「199」或「199」,「200」或「300」,「20」和「500」。 – abarnert 2013-02-28 18:39:22

+0

我想盡可能通用,因爲我的另一個規則是使用不同的正則表達式,不能按照您的建議分割。如果我爲這種情況使用split,我必須添加一個我不太喜歡的if-else語句。 – lhe 2013-02-28 18:41:16

+1

@lightmanhk:向我們展示實際的輸入字符串,就像它們在代碼中出現的一樣,並有足夠的多樣性向我們展示所有情況以及期望的輸出。否則,我們必須讀懂你的想法,弄清楚你想要什麼。 – abarnert 2013-02-28 18:42:16