re.findall se comporta raro

La cadena fuente es:

# Python 3.4.3 s = r'abc123d, hello 3.1415926, this is my book' 

y aquí está mi patrón:

 pattern = r'-?[0-9]+(\\.[0-9]*)?|-?\\.[0-9]+' 

sin embargo, re.search me puede dar un resultado correcto:

 m = re.search(pattern, s) print(m) # output:  

re.findall acaba de volcar una lista vacía:

 L = re.findall(pattern, s) print(L) # output: ['', '', ''] 

¿Por qué no puedo re.findall a darme la lista esperada?

 ['123', '3.1415926'] 

 s = r'abc123d, hello 3.1415926, this is my book' print re.findall(r'-?[0-9]+(?:\.[0-9]*)?|-?\.[0-9]+',s) 

No necesitas escape dos veces cuando estás usando raw mode .

Salida: ['123', '3.1415926']

También el tipo de retorno será una lista de strings . Si desea el tipo de retorno como integers y floats use map

 import re,ast s = r'abc123d, hello 3.1415926, this is my book' print map(ast.literal_eval,re.findall(r'-?[0-9]+(?:\.[0-9]*)?|-?\.[0-9]+',s)) 

Salida: [123, 3.1415926]

Hay dos cosas a tener en cuenta aquí:

  • re.findall devuelve los textos capturados si el patrón de re.findall regulares contiene grupos de captura en él
  • la r'\\.' parte de su patrón coincide con dos caracteres consecutivos, \ y cualquier char que no sea una nueva línea.

Ver referencia de findall :

Si uno o más grupos están presentes en el patrón, devuelva una lista de grupos; esta será una lista de tuplas si el patrón tiene más de un grupo. Las coincidencias vacías se incluyen en el resultado a menos que toquen el comienzo de otra coincidencia.

Tenga en cuenta que para que re.findall devuelva solo los valores coincidentes , normalmente puede

  • eliminar grupos de captura redundantes (por ejemplo, (a(b)c) -> abc )
  • convierta todos los grupos de captura en no captura (es decir, reemplace ( con (?: 🙂 a menos que haya referencias inversas que se refieran a los valores del grupo en el patrón (ver más abajo)
  • use re.finditer en re.finditer lugar ( [x.group() for x in re.finditer(pattern, s)] )

En su caso, findall devolvió todos los textos capturados que estaban vacíos porque tiene \\ dentro r'' cadena literal de r'' que trató de coincidir con un literal \ .

Para hacer coincidir los números, debe utilizar

 -?\d*\.?\d+ 

Los partidos de expresiones regulares:

  • -? – Signo menos opcional
  • \d* – dígitos opcionales
  • \.? – Separador decimal opcional.
  • \d+ – 1 o más dígitos.

Ver demo

Aquí está la demo IDEONE :

 import re s = r'abc123d, hello 3.1415926, this is my book' pattern = r'-?\d*\.?\d+' L = re.findall(pattern, s) print(L)