2

我有一个有效的正则表达式,它给了我想要的结果,但它不包含它需要的安全性。(万无一失)

假设我有一个匹配路径部分的正则表达式,类似于:

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

这会将零到三个以斜杠“/”结尾的 [:\w] 字符分组。使用 ?: 在组的开头,它不会被发送回匹配的分组。因此,组合它们的外部组是。因此,我们只能得到完全分组的结果。

唯一的问题是我希望最后一部分也可能匹配一个文件。(所以不以斜杠结尾。)我什至更喜欢在没有正则表达式的斜杠的情况下将其取回,但我也可以轻松地去除结果末尾的斜杠。

非常感谢任何反馈。如果这是要走的路,我会将其添加为答案。

编辑:

它与:根据预定义的文件夹结构查找文件夹

更新/编辑:

根据迄今为止给出的所有答案,我提出了各种尝试,但最终它们都非常缓慢。

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'

我不完全确定如何加快速度!

4

3 回答 3

3

您的[]正则表达式中的 不会对正则表达式进行分组。它用于指定字符类。

也许这会奏效-

\w*/{0,10}

对于分组,只需使用()

(\w*/){0,10}

编辑

根据您编辑的问题,我认为您想要的是目录名称匹配 0-3 次,然后文件名也匹配。

假设文件名中只有字母(以及可选的最多三个字符扩展名)

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

这个很大但是可以分成两部分

这是你已经拥有的

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

还有我添加的

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

这是末尾的可选文件名。(如果它不是可选的,您可以删除最后一个?)。文件名本身可以仅由字母组成,也可以具有最多 3 个字符的扩展名

添加^并将$停止虚假匹配

>>> 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')
于 2013-03-21T08:57:28.057 回答
1

取而代之的是,由于灾难性的回溯,这确实非常缓慢,

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

试试这个

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

或这个

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

您可能需要考虑一种方法,首先使用re.match和模式验证字符串,例如(\w:)?(/\w+)+$

然后,当您已经可以预期某种结构时,您可以使用更简单的正则表达式来提取数据:

/?([^/]*(?:/[^/]+)*)/dev/model/
于 2013-03-21T21:12:09.987 回答
0

你不能像在这儿那样[]放进去。相反,您想使用括号进行分组。[]([[\w]*/]{0,10})

试试这个:

>>> re.match(r'(\w*/){0,10}', 'abc/def/ghi/').group()
'abc/def/ghi/'
于 2013-03-21T08:57:43.267 回答