2012-09-26 118 views
10

我可以用什么正则表达式匹配“。#,#”。在一个字符串内。它可能存在或不存在于字符串中。预期输出的一些示例可能是:Python/Regex - Match。#,#。 in String

Test1.0,0.csv  -> ('Test1', '0,0', 'csv')   (Basic Example) 
Test2.wma   -> ('Test2', 'wma')    (No Match) 
Test3.1100,456.jpg -> ('Test3', '1100,456', 'jpg') (Basic with Large Number) 
T.E.S.T.4.5,6.png -> ('T.E.S.T.4', '5,6', 'png')  (Doesn't strip all periods) 
Test5,7,8.sss  -> ('Test5,7,8', 'sss')   (No Match) 
Test6.2,3,4.png -> ('Test6.2,3,4', 'png')   (No Match, to many commas) 
Test7.5,6.7,8.test -> ('Test7', '5,6', '7,8', 'test') (Double Match?) 

最后一个不是太重要,我只希望那个。#,#。会出现一次。我正在处理的大部分文件,我都希望属于第一到第四个例子,所以我最感兴趣的是这些文件。

感谢您的帮助!

+4

Awww man。如果只有每个人都能提供如此广泛的例子以及相匹配的例子和失败的例子...... –

+0

@ m.buettner我知道,这与99%的正则表达式问题相比很漂亮 – JKirchartz

回答

3

以允许多个连续两场比赛,用超前/回顾后:

r'(?<=\.)\d+,\d+(?=\.)' 

例子:

>>> re.findall(r'(?<=\.)\d+,\d+(?=\.)', 'Test7.5,6.7,8.test') 
['5,6', '7,8'] 

我们也可以用先行进行分割,只要你想它:

import re 
def split_it(s): 
    pieces = re.split(r'\.(?=\d+,\d+\.)', s) 
    pieces[-1:] = pieces[-1].rsplit('.', 1) # split off extension 
    return pieces 

测试:

>>> print split_it('Test1.0,0.csv') 
['Test1', '0,0', 'csv'] 
>>> print split_it('Test2.wma') 
['Test2', 'wma'] 
>>> print split_it('Test3.1100,456.jpg') 
['Test3', '1100,456', 'jpg'] 
>>> print split_it('T.E.S.T.4.5,6.png') 
['T.E.S.T.4', '5,6', 'png'] 
>>> print split_it('Test5,7,8.sss') 
['Test5,7,8', 'sss'] 
>>> print split_it('Test6.2,3,4.png') 
['Test6.2,3,4', 'png'] 
>>> print split_it('Test7.5,6.7,8.test') 
['Test7', '5,6', '7,8', 'test'] 
+0

+1,这是很好的使用lookahead。 –

+0

雅,非常好用的lookahead,谢谢! –

0

使用正则表达式^([^,]+)\.(\d+,\d+)\.([^,.]+)$

检查this demo >>

>>> print re.findall(r'^([^,]+)\.(\d+,\d+)\.([^,.]+)$', 'Test1.0,0.csv') 
[('Test1', '0,0', 'csv')] 

>>> print re.findall(r'^([^,]+)\.(\d+,\d+)\.([^,.]+)$', 'Test2.wma') 
[] 

>>> print re.findall(r'^([^,]+)\.(\d+,\d+)\.([^,.]+)$', 'Test3.1100,456.jpg') 
[('Test3', '1100,456', 'jpg')] 

>>> print re.findall(r'^([^,]+)\.(\d+,\d+)\.([^,.]+)$', 'T.E.S.T.4.5,6.png') 
[('T.E.S.T.4', '5,6', 'png')] 

>>> print re.findall(r'^([^,]+)\.(\d+,\d+)\.([^,.]+)$', 'Test5,7,8.sss') 
[] 

>>> print re.findall(r'^([^,]+)\.(\d+,\d+)\.([^,.]+)$', 'Test6.2,3,4.png') 
[] 

>>> print re.findall(r'^([^,]+)\.(\d+,\d+)\.([^,.]+)$', 'Test7.5,6.7,8.test') 
[] 
+0

这产生了什么:'Test.xx ,yz.csv'? – Dave

0
'/^(.+)\.((\d+,\d+)\.)?(.+)$/' 

第三捕获组应包含一对数字。如果你有多对,你应该得到多个匹配。第三次捕获将始终包含这对。

0
^(.*?)\.(\d+,\d+)\.(.*?)$ 

这通过你的测试,至少在模式:

Passing tests in Patterns

+0

什么是模式? –

+0

http://itunes.apple.com/us/app/patterns-the-regex-app/id429449079 –

4

您可以使用正则表达式\.\d+,\d+\.找到该模式的所有比赛,但你需要做一些额外的到得到你期望的输出,尤其是因为你想把.5,6.7,8.当作两场比赛。

这是一个潜在的解决方案:

def transform(s): 
    s = re.sub(r'(\.\d+,\d+)+\.', lambda m: m.group(0).replace('.', '\n'), s) 
    return tuple(s.split('\n')) 

例子:

>>> transform('Test1.0,0.csv') 
('Test1', '0,0', 'csv') 
>>> transform('Test2.wma') 
('Test2.wma',) 
>>> transform('Test3.1100,456.jpg') 
('Test3', '1100,456', 'jpg') 
>>> transform('T.E.S.T.4.5,6.png') 
('T.E.S.T.4', '5,6', 'png') 
>>> transform('Test5,7,8.sss') 
('Test5,7,8.sss',) 
>>> transform('Test6.2,3,4.png') 
('Test6.2,3,4.png',) 
>>> transform('Test7.5,6.7,8.test') 
('Test7', '5,6', '7,8', 'test') 

也得到文件的扩展名分离出来时,有没有比赛,你可以使用以下命令:

def transform(s): 
    s = re.sub(r'(\.\d+,\d+)+\.', lambda m: m.group(0).replace('.', '\n'), s) 
    groups = s.split('\n') 
    groups[-1:] = groups[-1].rsplit('.', 1) 
    return tuple(groups) 

除了'Test2.wma'变成之外,这将与上述输出相同,具有类似的行为'Test5,7,8.sss''Test5,7,8.sss'

+0

我会建议...这是一个链接到演示:http://regexr.com?329f8 – JKirchartz

+0

如果名称中有空格,则不起作用... – nneonneo

+0

另外,如果最后一个组包含多个“。”,则最终将最后一个组拆分几次。 – nneonneo

0

这很接近,python是否支持命名组?

^.*(?P<group1>\d+(?:,\d+)?)\.(?P<group2>\d+(?:,\d+)?).*\..+$ 
+0

命名组语法是'(?P 模式)' –

相关问题