2012-05-19 90 views
1

問:

我如何使用Python的正則表達式模塊(re),以確定是否匹配已經取得,或潛在的匹配可以作出?Python的正則表達式匹配的或潛在的匹配

詳情:

我想要的搜索按正確的順序,無論他們之間什麼是字的圖案的正則表達式。我想要一個函數返回Yes如果找到,Maybe如果仍然可以找到匹配或No如果不能找到匹配。我們正在尋找的模式One|....|Two|....|Three,這裏是一些例子(注意名稱,他們的數量,或他們的順序並不重要,我所關心的是三個詞One,TwoThree,其間可接受的詞是JohnMalkovich,StamosTravolta)。

返回YES:

One|John|Malkovich|Two|John|Stamos|Three|John|Travolta 

返回YES:

One|John|Two|John|Three|John 

返回YES:

One|Two|Three 

返回MAYBE:

One|Two 

返回MAYBE:

One 

返回NO:

Three|Two|One 

我理解的例子並不密閉,所以這裏是我正則表達式得到YES:

if re.match('One\|(John\||Malkovich\||Stamos\||Travolta\|)*Two\|(John\||Malkovich\||Stamos\||Travolta\|)*Three\|(John\||Malkovich\||Stamos\||Travolta\|)*', 'One|John|Malkovich|Two|John|Stamos|Three|John|Travolta') != None 
    return 'Yes' 

顯然,如果該模式是Three|Two|One上面會失敗,我們可以返回No,但我要如何檢查是否有Maybe情況?我想嵌套括號,像這樣(注意,未經測試)

if re.match('One\|((John\||Malkovich\||Stamos\||Travolta\|)*Two(\|(John\||Malkovich\||Stamos\||Travolta\|)*Three\|(John\||Malkovich\||Stamos\||Travolta\|)*)*)*', 'One|John|Malkovich|Two|John|Stamos|Three|John|Travolta') != None 
    return 'Yes' 

但我不認爲這會做我想做的事。

更多詳細信息:

我沒有真正尋找TravoltasMalkovichs(令人震驚,我知道)。我正在匹配inotify模式,如IN_MOVE,IN_CREATE,IN_OPEN,我記錄它們並獲得數百個,然後我進入,然後尋找特定模式,如IN_ACCESS ... IN_OPEN .... IN_MODIFY,但在某些情況下,我不希望IN_OPEN之後的IN_DELETE以及我在其他人中的IN_DELETE。我基本上是模式匹配使用的inotify時文本編輯器狂野來檢測,他們試圖做一個粉碎程序員的靈魂,而不是臨時文件交換保存的只是修改文件。我不想立即釋放這些日誌,但我只想保留它們,只要有必要。 Maybe表示不擦除日誌。 Yes方式做事情,然後刪除日誌和No手段沒有做任何事情,但還是刪除日誌。正如我將有多個規則,每個程序(即vim v gedit v emacs)我想用正則表達式這將是更可讀,更容易編寫,然後創建一個巨大的樹,或爲用戶Joel建議,只是在看帶有循環的詞

+1

您確定使用正則表達式是正確的方法嗎?我們可以簡單地在word.split()中單詞[wordList]中的單詞],然後檢查該列表的順序。 –

+0

@JoelCornett嗯。查看編輯plz – puk

+3

'Two | Three'會返回什麼?或'一|三'? –

回答

3

有些人在遇到問題時會想:「我知道,我會用正則表達式。」現在他們有兩個問題。 - 傑米Zawinski

也許像這樣的算法會更合適。這是一些僞代碼。

matchlist.current = matchlist.first() 
for each word in input 
    if word = matchlist.current 
     matchlist.current = matchlist.next() // assuming next returns null if at end of list 
    else if not allowedlist.contains(word) 
     return 'No' 
if matchlist.current = null // we hit the end of the list 
    return 'Yes' 
return 'Maybe' 
+1

+1對於報價 – puk

+0

我認爲你的僞代碼有錯誤。 '='在第3行是相等,而在第4行是用於分配 – puk

+1

@puk:這是有意的。僞代碼可以做任何事情;) –

3

我不會爲此使用正則表達式。但它絕對有可能:

regex = re.compile(
    r"""^   # Start of string 
    (?:    # Match... 
    (?:   # one of the following: 
     One()   # One (use empty capturing group to indicate match) 
    |    # or 
     \1Two()  # Two if One has matched previously 
    |    # or 
     \1\2Three() # Three if One and Two have matched previously 
    |    # or 
     John   # any of the other strings 
    |    # etc. 
     Malkovich 
    | 
     Stamos 
    | 
     Travolta 
    )    # End of alternation 
    \|?   # followed by optional separator 
    )*    # any number of repeats 
    $    # until the end of the string.""", 
    re.VERBOSE) 

現在,您可以檢查YES,也許通過檢查,如果你得到一個比賽都:

>>> yes = regex.match("One|John|Malkovich|Two|John|Stamos|Three|John|Travolta") 
>>> yes 
<_sre.SRE_Match object at 0x0000000001F90620> 
>>> maybe = regex.match("One|John|Malkovich|Two|John|Stamos") 
>>> maybe 
<_sre.SRE_Match object at 0x0000000001F904F0> 

而且你可以YES之間,也許通過檢查是否所有的區分各組都參加了比賽(即不None):

>>> yes.groups() 
('', '', '') 
>>> maybe.groups() 
('', '', None) 

如果正則表達式不匹配可言,那是一個沒有你:

>>> no = regex.match("Three|Two|One") 
>>> no is None 
True 
+1

這肯定看起來使事情更難,然後將列表和樹木 – puk

+1

+1了詳細的解釋,但是這使得我的頭不疼:) – Levon