Extraer múltiples cadenas usando la expresión regular de Pythons

Tengo un archivo de registro con el siguiente resultado y lo he reducido a miles de líneas:

Time = 1 smoothSolver: Solving for Ux, Initial residual = 0.230812, Final residual = 0.0134171, No Iterations 2 smoothSolver: Solving for Uy, Initial residual = 0.283614, Final residual = 0.0158797, No Iterations 3 smoothSolver: Solving for Uz, Initial residual = 0.190444, Final residual = 0.016567, No Iterations 2 GAMG: Solving for p, Initial residual = 0.0850116, Final residual = 0.00375608, No Iterations 3 time step continuity errors : sum local = 0.00999678, global = 0.00142109, cumulative = 0.00142109 smoothSolver: Solving for omega, Initial residual = 0.00267604, Final residual = 0.000166675, No Iterations 3 bounding omega, min: -26.6597 max: 18468.7 average: 219.43 smoothSolver: Solving for k, Initial residual = 1, Final residual = 0.0862096, No Iterations 2 ExecutionTime = 4.84 s ClockTime = 5 s Time = 2 smoothSolver: Solving for Ux, Initial residual = 0.0299872, Final residual = 0.00230507, No Iterations 2 smoothSolver: Solving for Uy, Initial residual = 0.145767, Final residual = 0.00882969, No Iterations 3 smoothSolver: Solving for Uz, Initial residual = 0.0863129, Final residual = 0.00858536, No Iterations 2 GAMG: Solving for p, Initial residual = 0.394189, Final residual = 0.0175138, No Iterations 3 time step continuity errors : sum local = 0.00862823, global = 0.00212477, cumulative = 0.00354587 smoothSolver: Solving for omega, Initial residual = 0.00258475, Final residual = 0.000222705, No Iterations 3 smoothSolver: Solving for k, Initial residual = 0.112805, Final residual = 0.0054572, No Iterations 3 ExecutionTime = 5.9 s ClockTime = 6 s Time = 3 smoothSolver: Solving for Ux, Initial residual = 0.128298, Final residual = 0.0070293, No Iterations 2 smoothSolver: Solving for Uy, Initial residual = 0.138825, Final residual = 0.0116437, No Iterations 3 smoothSolver: Solving for Uz, Initial residual = 0.0798979, Final residual = 0.00491246, No Iterations 3 GAMG: Solving for p, Initial residual = 0.108748, Final residual = 0.00429273, No Iterations 2 time step continuity errors : sum local = 0.0073211, global = -0.00187909, cumulative = 0.00166678 smoothSolver: Solving for omega, Initial residual = 0.00238456, Final residual = 0.000224435, No Iterations 3 smoothSolver: Solving for k, Initial residual = 0.0529661, Final residual = 0.00280851, No Iterations 3 ExecutionTime = 6.92 s ClockTime = 7 s 

Necesito extraer Time = 1, 2, 3 y los valores acumulativos correspondientes usando la expresión regular de Python. Más precisamente, necesito extraer solo los valores 1, 2, 3 y 0.00142109, 0.00354587, 0.00166678 que corresponde a acumulativo en Tiempo = 1,2 y 3 y escribir en otro archivo.

Actualmente, esto es lo que tengo:

 contCumulative_0_out = open('contCumulative_0', 'w+') with open(logFile, 'r') as logfile_read: for line in logfile_read: line = line.rstrip() iteration_time = re.findall(r'^Time = ([0-9]+)', line) print iteration_time contCumulative_0 = re.search(r'cumulative = ((\d|.)+)', line) if contCumulative_0: cumvalue = contCumulative_0.groups(1) contCumulative_0_out.write('\n'.join(cumvalue)) 

La variable iteration_time toma el valor del Tiempo, sin embargo, no está disponible en el siguiente bucle if posterior y, por lo tanto, no puedo combinar el Tiempo y el acumulado para obtener 1 0.00142109 en el archivo de salida.

Cuando no hay ‘Tiempo’ o ‘acumulativo’ en esta línea, no hay necesidad de sobrescribir esa variable. Puedes hacerlo:

 ... with open(logFile, 'r') as logfile_read: for line in logfile_read: line = line.rstrip() if 'Time' in line: iteration_time = re.findall(r'^Time = ([0-9]+)', line) print iteration_time if 'cumulative' in line: contCumulative_0 = re.search(r'cumulative = ((\d|.)+)', line) if contCumulative_0: cumvalue = contCumulative_0.groups(1) contCumulative_0_out.write('\n'.join(cumvalue)) ... 

Su código está escribiendo iteration_time en cada iteración del bucle for . Ese es el problema. Deberá dejar de rellenar esta variable una vez que se haya completado correctamente para la primera búsqueda.

Para hacer esto, en el bucle for haga una prueba para iteration_time y solo si no existe o None hace la búsqueda de expresiones regulares para Time. Puedes hacer algo así:

 contCumulative_0_out = open('contCumulative_0', 'w+') with open(logFile, 'r') as logfile_read: iteration_time = None for line in logfile_read: line = line.rstrip() time_match = re.findall(r'^Time = ([0-9]+)', line) if time_match: iteration_time = time_match print iteration_time else: # Because if there is time_match, there is no 'cumulative = ...' contCumulative_0 = re.search(r'cumulative = ((\d|.)+)', line) if contCumulative_0: cumvalue = contCumulative_0.groups(1) # You can check and use iteration_time here contCumulative_0_out.write('\n'.join(cumvalue)) 

Espero que esto ayude.

Puede hacer esto con una expresión regular, asumiendo que su formato de registro es el mismo para todas sus entradas. La explicación de lo que está pasando es a continuación:

 import re s = """Time = 1 smoothSolver: Solving for Ux, Initial residual = 0.230812, Final residual = 0.0134171, No Iterations 2 smoothSolver: Solving for Uy, Initial residual = 0.283614, Final residual = 0.0158797, No Iterations 3 smoothSolver: Solving for Uz, Initial residual = 0.190444, Final residual = 0.016567, No Iterations 2 GAMG: Solving for p, Initial residual = 0.0850116, Final residual = 0.00375608, No Iterations 3 time step continuity errors : sum local = 0.00999678, global = 0.00142109, cumulative = 0.00142109 smoothSolver: Solving for omega, Initial residual = 0.00267604, Final residual = 0.000166675, No Iterations 3 bounding omega, min: -26.6597 max: 18468.7 average: 219.43 smoothSolver: Solving for k, Initial residual = 1, Final residual = 0.0862096, No Iterations 2 ExecutionTime = 4.84 s ClockTime = 5 s Time = 2 smoothSolver: Solving for Ux, Initial residual = 0.230812, Final residual = 0.0134171, No Iterations 2 smoothSolver: Solving for Uy, Initial residual = 0.283614, Final residual = 0.0158797, No Iterations 3 smoothSolver: Solving for Uz, Initial residual = 0.190444, Final residual = 0.016567, No Iterations 2 GAMG: Solving for p, Initial residual = 0.0850116, Final residual = 0.00375608, No Iterations 3 time step continuity errors : sum local = 0.00999678, global = 0.00142109, cumulative = 0.00123456 smoothSolver: Solving for omega, Initial residual = 0.00267604, Final residual = 0.000166675, No Iterations 3 bounding omega, min: -26.6597 max: 18468.7 average: 219.43 smoothSolver: Solving for k, Initial residual = 1, Final residual = 0.0862096, No Iterations 2 ExecutionTime = 4.84 s ClockTime = 5 s """ regex = re.compile("^Time = (\d+?).*?cumulative = (\d{0,10}\.\d{0,10})",re.DOTALL|re.MULTILINE) for x in re.findall(regex,s): print "{} => {}".format(x[0], x[1]) 

Esto genera dos resultados (porque he agregado dos entradas de registro, en lugar de solo la que proporcionó):

 1 => 0.00142109 2 => 0.00123456 

¿Que esta pasando?

El RegEx que se está utilizando es este:

 ^Time = (\d+?).*?cumulative = (\d{0,10}\.\d{0,10}) 

Este Regex está buscando su cadena de Time = al principio de la línea y coincide con el dígito que sigue. Luego hace una coincidencia no codiciosa con la cadena cumulative = y captura los dígitos que siguen. La no codicia es importante, de lo contrario solo obtendrías un resultado en todo tu registro porque coincidiría con la primera instancia de Time = y la última instancia de cumulative = .

Luego imprime cada resultado. Cada resultado capturado contiene el valor de tiempo y el valor acumulativo. Esta parte del código puede modificarse para imprimir en un archivo si es necesario.

Esta expresión regular funciona en varias líneas porque utiliza dos marcas : DOTALL y MULTILINE