¿Cómo hago una expresión regular para coincidir con la agrupación con un número desconocido de grupos?

Quiero hacer una coincidencia de expresiones regulares (en Python) en el registro de salida de un progtwig. El registro contiene algunas líneas que se ven así:

... VALUE 100 234 568 9233 119 ... VALUE 101 124 9223 4329 1559 ... 

Me gustaría capturar la lista de números que aparece después de la primera incidencia de la línea que comienza con VALUE. es decir, quiero que regrese ('100','234','568','9233','119') . El problema es que no sé de antemano cuántos números habrá.

Intenté usar esto como una expresión regular:

 VALUE (?:(\d+)\s)+ 

Esto coincide con la línea, pero solo captura el último valor, así que solo obtengo (‘119’,).

Lo que está buscando es un analizador , en lugar de una coincidencia de expresión regular. En su caso, consideraría usar un analizador muy simple, split() :

 s = "VALUE 100 234 568 9233 119" a = s.split() if a[0] == "VALUE": print [int(x) for x in a[1:]] 

Puede usar una expresión regular para ver si su línea de entrada coincide con el formato esperado (usando la expresión regular en su pregunta), luego puede ejecutar el código anterior sin tener que verificar "VALUE" y saber que la conversión int(x) se realizará siempre tiene éxito ya que ya confirmó que los siguientes grupos de caracteres son todos dígitos.

 >>> import re >>> reg = re.compile('\d+') >>> reg.findall('VALUE 100 234 568 9233 119') ['100', '234', '568', '9223', '119'] 

Eso no valida que la palabra clave “VALOR” aparezca al principio de la cadena, y no valida que exista exactamente un espacio entre los elementos, pero si puede hacerlo como un paso separado (o si no lo hace) No es necesario que haga eso), entonces encontrará todas las secuencias de dígitos en cualquier cadena.

Otra opción no descrita aquí es tener un grupo de grupos de captura opcionales.

 VALUE *(\d+)? *(\d+)? *(\d+)? *(\d+)? *(\d+)? *$ 

Esta expresión regular captura grupos de hasta 5 dígitos separados por espacios. Si necesita más grupos potenciales, solo copie y pegue más *(\d+)? bloques

Puede ejecutar su expresión regular de coincidencias principal y luego ejecutar una expresión regular secundaria en esas coincidencias para obtener los números:

 matches = Regex.Match(log) foreach (Match match in matches) { submatches = Regex2.Match(match) } 

Esto es, por supuesto, también si no desea escribir un analizador completo.

Tuve el mismo problema y mi solución fue usar dos expresiones regulares: la primera para coincidir con todo el grupo en el que estoy interesado y la segunda para analizar los subgrupos. Por ejemplo, en este caso, me gustaría comenzar con esto:

 VALUE((\s\d+)+) 

Esto debería dar como resultado tres coincidencias: [0] la línea completa, [1] la materia después del valor [2] el último espacio + valor.

[0] y [2] se pueden ignorar y luego [1] se puede usar con lo siguiente:

 \s(\d+) 

Nota: estas expresiones regulares no fueron probadas, aunque espero que tengas la idea.


La razón por la que la respuesta de Greg no me funciona es porque la segunda parte del análisis es más complicada y no simplemente algunos números separados por un espacio.

Sin embargo, honestamente me gustaría ir con la solución de Greg para esta pregunta (probablemente es mucho más eficiente).

Solo escribo esta respuesta en caso de que alguien esté buscando una solución más sofisticada como la que necesitaba.

Puede usar re.match para verificar primero y llamar a re.split para usar una expresión regular como separador para dividir.

 >>> s = "VALUE 100 234 568 9233 119" >>> sep = r"\s+" >>> reg = re.compile(r"VALUE(%s\d+)+"%(sep)) # OR r"VALUE(\s+\d+)+" >>> reg_sep = re.compile(sep) >>> if reg.match(s): # OR re.match(r"VALUE(\s+\d+)+", s) ... result = reg_sep.split(s)[1:] # OR re.split(r"\s+", s)[1:] >>> result ['100', '234', '568', '9233', '119'] 

El separador "\s+" puede ser más complicado.