Estoy tratando de extraer datos de un registro de cambios usando RegEx. Aquí hay un ejemplo de cómo se estructura el registro de cambios:

96545
this is some changes in the ticket
some new version: x.x.22
another change
new version: x.y.2.2
120091
this is some changes in the ticket
some new version: z.z.22
another change
another change
another change
new version: z.y.2.2
120092
...
...
...
  • Cada punto de datos comienza con una ID que tiene un rango de 5 a 6 dígitos.
  • Además, hay una cantidad variable de cambios (líneas) en el registro por ID.
  • Cada punto de datos termina con new version: ***. *** es una cadena que es variable para cada ID.

Estaba usando el RegExStrom Tester para probar mi RegEx.

Hasta ahora tengo: ^\w{5,6}(.|\n)*?\d{5,6} sin embargo, el resultado incluye la ID del próximo ticket, que debo evitar.

Resultado:

96545
this is some changes in the ticket
some new version: x.x.22
another change
new version: x.y.2.2
120091 

Resultado esperado:

96545
this is some changes in the ticket
some new version: x.x.22
another change
new version: x.y.2.2
2
Audiogott 4 oct. 2019 a las 20:36

4 respuestas

La mejor respuesta

Si el problema fue que capturó la ID del próximo Ticket, simplemente use una mirada positiva para mecanizarlo, pero no lo capture ni lo consuma:

# end of tickets is the end of line that the line after it contains the Id of the next ticket
pattern = r"\d{5,6}[\s\S]*?(?=\n\d{5,6})"

# to extract first ticket info just use search
print(re.search(pattern, text).group(0))

# to extract all tickets info in a list use findall
print(re.findall(pattern, text))

# if the file is to big and you want to extract tickets in lazy mode
for ticket in re.finditer(pattern,text):
    print(ticket.group(0))
1
Wiktor Stribiżew 8 oct. 2019 a las 19:44

Tu expresión regular está cerca. Su problema es que está "finalizando" al comienzo del siguiente registro, utilizando \d{5,6} para marcar el final de una entrada de registro (y coincidir en el proceso). Como mencionó Wiktor, tendría más sentido usar "nueva versión" como el delímetro, así que lo he hecho aquí.

found_matches = re.findall("(^\d{5,6}[\s\S]*?^new version: .*$)", log_file_content, re.MULTILINE)

La expresión regular (^\d{5,6}[\s\S]*?^new version: .*$) busca 5 o 6 dígitos al comienzo de la línea, y luego toma cualquier carácter (incluidas las nuevas líneas) hasta la primera instancia de new version: que aparece al comienzo de una línea. Luego se lee hasta el final de la línea para terminar ese grupo. Como va a coincidir entre líneas nuevas, asegúrese de recordar el argumento re.MULTILINE.

Pruebe la expresión regular aquí, y el código completo de Python aquí.

1
Nick Reed 4 oct. 2019 a las 19:32

Esto lo haría:

^\d{5,6}[\r\n]*.*?^new version:[^\r\n]*

Solo asegúrese de habilitar las banderas MULTILINE y DOTALL a través de re.MULTILINE | re.DOTALL

https://regex101.com/r/YeIUQx/1

1
MonkeyZeus 4 oct. 2019 a las 19:28

Captura cada ID de registros en el grupo 1 y el contenido en el grupo 2

r'(?ms)^(\d{5,6}\r?\n)(.*?)^new version:'

https://regex101.com/r/A3ejjN/1

3
x15 4 oct. 2019 a las 19:14
58240959