Regex: ¿Por qué se incluyen las cadenas vacías (en una lista de tuplas) en re.findall ()?

Según la coincidencia de patrón aquí , las coincidencias son 213.239.250.131 y 014.10.26.06 .

Sin embargo, cuando ejecuto el código Python generado e re.findall(p, test_str) el valor de re.findall(p, test_str) , obtengo:

 [('', '', '213.239.250.131'), ('', '', '014.10.26.06')] 

Podría hackear la lista y las tuplas para obtener los valores que estoy buscando (las direcciones IP), pero (i) puede que no siempre estén en la misma posición en las tuplas y (ii) prefiero entender qué es pasando aquí, así que puedo ajustar la expresión regular, o extraer solo las direcciones IP usando la funcionalidad re Python.

¿Por qué obtengo esta lista de tuplas, por qué coinciden los espacios en blanco aparentes y cómo nos aseguramos de que solo se devuelvan las direcciones IP?

Siempre que esté utilizando un grupo de captura , siempre devuelve una sub-coincidencia, incluso si está vacío / nulo. Tiene 3 grupos de captura, por lo que siempre los tendrá en el resultado general.

En regex101.com, puede ver estos grupos no participantes activándolos en Opciones:

introduzca la descripción de la imagen aquí

Puede ajustar su expresión regular eliminando los grupos de captura:

 (?:[a-z0-9]{1,4}:+){3,5}[a-z0-9]{1,4}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} 

O incluso (?:[a-z0-9]{1,4}:+){3,5}[a-z0-9]{1,4}|\d{1,3}(?:\.\d{1,3}){3} .

Ver una demostración de expresiones regulares

Y dado que el patrón de re.findall no contiene grupos de captura, re.findall solo devolverá coincidencias , no la captura de contenido de grupo :

 import re p = re.compile(r'(?:[a-z0-9]{1,4}:+){3,5}[a-z0-9]{1,4}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}') test_str = "from mail.example.com (example.com. [213.239.250.131]) by\n mx.google.com with ESMTPS id xc4si15480310lbb.82.2014.10.26.06.16.58 for\n  (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256\n bits=128/128); Sun, 26 Oct 2014 06:16:58 -0700 (PDT)" print(re.findall(p, test_str)) 

Salida de la demostración en línea de Python :

 ['213.239.250.131', '014.10.26.06'] 

Estos son los grupos de captura. Si lo hace o consulta, devolverá coincidencias vacías para las expresiones no coincidentes.

(([a-z0-9]{1,4}:+){3,5}[a-z0-9]{1,4})|(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})

El primero o tiene 2 grupos:
(([a-z0-9]{1,4}:+){3,5}[a-z0-9]{1,4})

y después del o hay el tercero:
(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})

para decirlo de una manera simple, cada paréntesis redondo define un grupo de captura que se mostrará si el valor coincide o no.