Python/Regex - Match. #, #. в 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?)

Последнее не слишком важно, и я бы только ожидал этого. #, #. появится один раз. Большинство файлов, которые я обрабатываю, я ожидаю, что они попадут в первый-четвертый примеры, поэтому меня больше всего интересуют эти.

Спасибо за помощь!

Ответ 1

Чтобы разрешить несколько последовательных совпадений, используйте lookahead/lookbehind:

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

Пример:

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

Мы также можем использовать lookahead для выполнения разбиения по вашему желанию:

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']

Ответ 2

Вы можете использовать regex \.\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' становится ('Test2', 'wma'), с аналогичным поведением для 'Test5,7,8.sss' и 'Test5,7,8.sss'.

Ответ 3

Использовать шаблон регулярного выражения ^([^,]+)\.(\d+,\d+)\.([^,.]+)$

Отметьте эту демонстрацию >

>>> 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') 
[]

Ответ 4

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

Третья группа захвата должна содержать пару чисел. Если у вас несколько пар, вы должны получить несколько совпадений. И третий захват всегда будет содержать пару.

Ответ 5

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

Это проходит ваши тесты, по крайней мере в шаблонах:

Passing tests in Patterns

Ответ 6

Это довольно близко, поддерживает ли python именованные группы?

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