2012-09-26 28 views
10

Qué expresiones regulares puedo usar para que coincida con ". #, #." dentro de una cadena. Puede o no existir en la cadena. Algunos ejemplos con salidas esperadas pueden ser:Python/Regex - Match. #, #. en 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?) 

La última no es demasiado importante y solo esperaría que. #, #. aparecería una vez La mayoría de los archivos que estoy procesando, espero que caigan en el primero al cuarto ejemplo, por lo que estoy más interesado en ellos.

¡Gracias por la ayuda!

+4

Awww hombre. Si solo todos proporcionaran una lista tan extensa de ejemplos que coinciden y ejemplos que fallan ... –

+0

@ m.buettner Lo sé, esto es hermoso en comparación con el 99% de las preguntas de expresiones regulares – JKirchartz

Respuesta

3

para permitir múltiples partidos consecutivos, utilizar búsqueda hacia delante/búsqueda hacia atrás:

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

Ejemplo:

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

También podemos utilizar búsqueda hacia delante para llevar a cabo la escisión como quiera que:

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

Pruebas:

>>> 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, este es un buen uso de lookaheads. –

+0

Ya, muy buen uso de lookahead, gracias! –

0

patrón de uso de expresiones regulares ^([^,]+)\.(\d+,\d+)\.([^,.]+)$

Comprobar 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

¿Qué significa esto para: 'Test.xx , yz.csv'? – Dave

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

El tercer grupo de captura debe contener el par de números. Si tiene varios de esos pares, debe obtener múltiples coincidencias. Y la tercera captura siempre contendría el par.

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

Esto pasa sus pruebas, al menos en los patrones:

Passing tests in Patterns

+0

¿Qué es Patrones? –

+0

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

4

Puede utilizar la expresión regular \.\d+,\d+\. para encontrar todos los partidos de ese patrón, pero tendrá que hacer un poco más para Obtenga el resultado que espera, especialmente porque quiere tratar .5,6.7,8. como dos coincidencias.

Aquí es una posible solución:

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

Ejemplos:

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

Para conseguir también la extensión del archivo se separó cuando no hay coincidencias, puede utilizar el siguiente:

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) 

Esta será la misma salida que la anterior excepto que 'Test2.wma' se convierte en ('Test2', 'wma'), con un comportamiento similar para 'Test5,7,8.sss' y 'Test5,7,8.sss'.

+0

Iba a sugerir que ... aquí hay un enlace a una demostración: http://regexr.com?329f8 – JKirchartz

+0

No funciona del todo si hay espacios en el nombre ... – nneonneo

+0

Además, si el último grupo contiene más de un '.' terminará dividiendo el último grupo varias veces. – nneonneo

0

Esto está bastante cerca, ¿el soporte de Python tiene los nombres de grupos?

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

La sintaxis del grupo nombrado es '(? P patrón)' –