捕获文件名部分:为什么这个正则表达式不起作用?

时间:2016-05-20 08:30:38

标签: regex

我对regexp很新,而且我错过了捕捉群体的一些东西。

假设我有一个类似

的文件路径
test.orange.john.edn

我想捕捉两组:

test.orange.john (which is the body)
edn (which is the extension)

我使用了它(以及它的变体,将$取出等等)

^([a-z]*.)*.([a-z]*$)

但它仅捕获xm

我错过了什么?我不明白为什么我没被捕获,身体也是...... 我在网上找到答案来捕获扩展,但我不明白那里的问题。

由于

2 个答案:

答案 0 :(得分:2)

^([a-z]*.)*.([a-z]*$)正则表达式的效率非常低,因为这里有许多不必要的回溯步骤。

匹配字符串的开头,然后[a-z]*.匹配0次以上。这意味着,引擎尽可能多地[a-z]匹配(即它匹配test直到第一个点),然后.匹配点(但只是因为.匹配任何角色!)。因此,此([a-z]*.)*仅匹配test.orange.john.edn 捕获edn,因为重复捕获组仅保留最后捕获的值。

您已在第1组at this step中拥有edn。现在,.([a-z]*$)应该为.(任何字符)模式分配子字符串。回溯返回并找到n - 现在,Group 1 only contains ed

对于你的任务,你应该逃避最后的.以匹配文字点,也许,最好的表达是

^(.*)\.(.*)$

请参阅demo

它会将所有字符串与第一个(.*)匹配到最后,然后将回溯以查找最后一个.符号(因此,第1组将包含从开头到结尾的所有文本最后.),然后将其余字符串捕获到第2组。

如果不必存在点(即文件名没有扩展名),请添加一个可选组:

^(.*)(?:\.(.*))?$

请参阅another demo

答案 1 :(得分:0)

您可以尝试:

In [1025]: def f(d):
    for k, v in d.items():
        yield (k, d[k].keys()[0], d[k].values()[0])
   ......:         

In [1026]: for i in f(d):

    print i
   ......:     
('a', 'x', 45)
('b', 'r', 34)

online example