2013-03-21 50 views
2

我有一個工作正則表達式給了我想要的結果,但它並沒有包含它所需要的安全性。 (防呆)Python正則表達式在模式內出現零次或多次出現

比方說,我有一個匹配的路線的部分地區,東西線沿線的一個正則表達式:我希望能夠更換匹配任何字符了,直到

import re 
path = "C:/Projects/foo/dev/model/props/furniture/couch/data/fbx" 
regex = re.compile("(.+)/dev/model/(.+)/(.+)/data/fbx") 
m = regex.search(path) 
if m: 
    print m.groups() 

# ('C:/Projects/foo', 'props/furniture', 'couch') 

跟隨正則表達式的一部分,其中某些匹配一個或多個文件夾。

比方說,我們定義了一個文件夾以斜線結束簡單的單詞字符(沒有或更多)這將是:

[\w]*/ 

我想組零到那些十,我會怎麼做那?

在我心目中,我有這樣的事情(注意,這不工作!):

# match any number of word characters ending with a slash zero to ten times 
([[\w]*/]{0,10}) 

# match any number of word characters ending with a slash zero to one time 
([[\w]*/]?) 

編輯:

基於RedBaron和jamylak的答案,我想出了以下內容:

((?:[:\w]+/){0,3}) 

這將組0到3個以斜槓'/'結尾的字符[:\ w]。使用?:在組的開頭不會被髮送回匹配的分組。所以,結合他們的外部團體是。因此我們只得到完全分組的結果。

唯一的問題是,我希望最後一部分也可能匹配一個文件。 (所以不要以斜槓結尾。)我甚至更喜歡將它從正則表達式中刪除,但我也可以輕鬆地刪除結果的結尾。

任何反饋,非常感謝。如果這是要走的路,我會將其添加爲答案。

編輯:

它涉及到:Finding folders back based on a predefined folder structure

UPDATE /編輯:

基於迄今爲止給出的所有答案,我想出了各種各樣的嘗試,但他們最終所有結果都極其緩慢。

import re 
path = "C:/Projects/foo/dev/model/props/furniture/couch/data/fbx" 
regex = re.compile(r"""((?:^(?:[\w:]+/?)+)|(?:(?<=/)(?:[\w]+/?)+))/dev/model/""") 
print 'search start' 
m = regex.search(path) 
print 'search done' 
if m: 
    print 'match', m, m.groups() 
else: 
    print 'no match' 

我並不完全知道如何加快速度!

+0

請顯示「路徑」示例的所需輸出。 – 2013-03-21 10:31:49

+0

從我的問題的頂部示例代碼給出的輸出是所需的輸出。但是我想爲比賽添加更多的功能,所以我可以更精確地定義它。例如,只匹配兩到四個文件夾。 – 2013-03-21 10:55:48

回答

1

您的正則表達式中的[]不會對正則表達式進行分組。它用於指定字符類。

也許這將與工作

\w*/{0,10} 

而對於分組只使用()

(\w*/){0,10} 

編輯

根據您編輯的問題,我想你想要的是0出現-3次匹配的目錄名稱,然後文件名稱也匹配。

假設在文件名中唯一的字母(和一個可選的高達三個字符的擴展名)

^((?:[:\w]+/){0,3})(\w+(?:\.\w{1,3})?)?$ 

這是非常大的,但可以分成兩個部分

這是你已經擁有

((?:[:\w]+/){0,3}) 

而我添加

(\w+(?:\.\w{1,3})?)? 

這是最後一個可選的文件名。 (如果不是可選的,你可以刪除最後的?)。本身既可以僅由alphabtes或也文件名具有最大3個字符

添加^$的延伸將停止spurous比賽

>>> pat=re.compile('^((?:[:\w]+/){0,3})(\w+(?:\.\w{1,3})?)?$') 
>>> my_str='fwefw/wfwf/wefwf/dde.cdf' 
>>> pat.search(my_str).groups() 
('fwefw/wfwf/wefwf/', 'dde.cdf') 
>>> my_str='fwefw/dde.cdf' 
>>> pat.search(my_str).groups() 
('fwefw/', 'dde.cdf') 
+0

這會將他們分組。我已經完成了一項測試(請參閱上面編輯的帖子),以便它僅將完全分組的結果作爲一個組返回。這是應該做的方式嗎? – 2013-03-21 09:21:24

+0

我編輯了答案 – RedBaron 2013-03-21 09:49:06

+0

謝謝!我試圖匹配路徑中的一些可變部分(請參閱我的問題中的添加鏈接)。我還添加了一個新的嘗試,但它變得非常緩慢! – 2013-03-21 16:09:32

0

你不能把[][]像你這樣這裏([[\w]*/]{0,10})。相反,你想用括號來分組。相反

>>> re.match(r'(\w*/){0,10}', 'abc/def/ghi/').group() 
'abc/def/ghi/' 
+0

太棒了。基於你的回答,我似乎已經找到了我需要的東西。 ;)我會在一秒鐘後發佈。如果您發現任何錯誤,請告知我。 – 2013-03-21 09:03:24

1

的這一點,這是確因catastrophic backtracking很慢,

((?:^(?:[\w:]+/?)+)|(?:(?<=/)(?:[\w]+/?)+))/dev/model/ 

試試這個

(^[\w:]+(?:/\w+)*|(?<=/)\w+(?:/\w+)*)/dev/model/ 

或本

試試這個3210


你可能要考慮的方法,你首先確認使用re.match和模式,如(\w:)?(/\w+)+$

那麼字符串時,你可以期待一定的結構已經,你可以使用一個簡單的正則表達式提取數據:

/?([^/]*(?:/[^/]+)*)/dev/model/ 
相關問題