2012-09-26 46 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 模式)' –

相關問題