2013-03-21 51 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/ 
相关问题