Quiero procesar cada línea en mi archivo de registro y extraer la IP
dirección si la línea coincide con mi patrón. Hay varios tipos diferentes de mensajes, en el ejemplo a continuación estoy usando p1 and
p2`.
Podía leer el archivo línea por línea, y para cada línea coincidir con cada patrón. Pero como puede haber muchos más patrones, me gustaría hacerlo de la manera más eficiente posible. Esperaba compilar estos patrones en un objeto, y hacer la coincidencia solo una vez para cada línea:
import re
IP = r'(?P<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'
p1 = 'Registration from' + IP + '- Wrong password'
p2 = 'Call from' + IP + 'rejected because extension not found'
c = re.compile(r'(?:' + p1 + '|' + p2 + ')')
for line in sys.stdin:
match = re.search(c, line)
if match:
print(match['ip'])
pero el código anterior no funciona, se queja de que ip
se usa dos veces.
¿Cuál es la forma más elegante de lograr mi objetivo?
EDITAR:
He modificado mi código basado en la respuesta de @Dev Khadka.
Pero todavía estoy luchando sobre cómo manejar adecuadamente las múltiples ip
coincidencias. El siguiente código imprime todas las IP que coinciden con p1:
for line in sys.stdin:
match = c.search(line)
if match:
print(match['ip1'])
Pero algunas líneas no coinciden p1
. Ellos coinciden p2
. es decir, obtengo:
1.2.3.4
None
2.3.4.5
...
¿Cómo se imprime la IP correspondiente, cuando no sé que era wheter p1
, p2
, ...? Todo lo que quiero es la IP. No me importa qué patrón coincida.
fuente
Respuestas:
Puede considerar instalar el excelente
regex
módulo, que admite muchas características avanzadas de expresiones regulares, incluidos los grupos de restablecimiento de rama , diseñados para resolver exactamente el problema que describió en esta pregunta. Los grupos de restablecimiento de rama se denotan por(?|...)
. Todos los grupos de captura de las mismas posiciones o nombres en diferentes patrones alternativos dentro de un grupo de restablecimiento de rama comparten los mismos grupos de captura para la salida.Observe que en el ejemplo a continuación, el grupo de captura coincidente se convierte en el grupo de captura con nombre, por lo que no necesita iterar sobre múltiples grupos buscando un grupo no vacío:
Demostración: https://repl.it/@blhsing/RegularEmbellishedBugs
fuente
¿Por qué no compruebas qué expresión regular coincide?
o algo como:
o incluso
fuente
match[i]
bucle for?if match[name] is not None:
IndexError: no such group
name in match
en su lugareso es porque estás usando el mismo nombre de grupo para dos grupos
intente esto, esto le dará los nombres de grupo ip1 e ip2
fuente
Los grupos de captura con nombre deben tener nombres distintos, pero dado que todos sus grupos de captura están destinados a capturar el mismo patrón, es mejor no usar grupos de captura con nombre en este caso, sino simplemente usar grupos de captura regulares e iterar a través de los grupos desde el objeto coincidente para imprimir el primer grupo que no está vacío:
Demostración: https://repl.it/@blhsing/UnevenCheerfulLight
fuente