Expresiones regulares
octubre 11, 2015
Expresiones regulares¶
La librería de expresiones regulares de Python (RE), contiene operaciones de comparación de texto, puede encontrar fragmentos o patrones de tipo string o unicode. Generalmente se usa el símbolo " \ " (backslash) para indicar caracteres especiales. Un ejemplo de estos caracteres es "\n" que representa una nueva línea en un texto:
print "Este caracter \nparte la línea en 2"
# Importación de la librería de expresiones regulares en Python
import re
search¶
Para buscar determinado fragmento de texto dadas ciertas condiciones se usa el método search contenido en la librería re. Este método requiere de dos argumentos un patrón y el texto en el que se realiza la búsqueda. Al imprimir el resultado se ve que es un objeto tipo '_sre.SRE_Match'. Si no encuentra el patrón el resultado de la búsqueda es None
result = re.search('ins', 'Vasili Kadinsky')
print result
print type(result)
result = re.search('arac', 'Caravaggio')
print result
Para ver el valor contenido en este objeto, en caso de encontrado el patrón, se usa el método group, que arroja el valor del patrón buscado.
result = re.search('ins', 'Vasili Kadinsky')
print result.group()
Es posible hacer búsquedas con un patrón que dependa del texto alrededor de este, por ejemplo, se busca el patrón 'ins' nuevamente pero esta vez debe estar seguido de dos letras minúsculas. Para indicar cada letra siguiente se usa la expresión regular " \w ". Si se requiere una bśuqueda en al que las letras continuas sean mayúsculas se usa " \W ".
result = re.search('ins\w\w', 'Vasili Kadinsky')
print result.group()
findall¶
Permite realizar búsquedas de un patrón en un string al igual que la función search, la diferencia es que search devuelve la primera coincidencia y findall encuentra todas las coincidencias
texto = u"Ella, ansiosa, Vuela y posa, En su palma sonrosada, Y allí mismo, ya saciada, Y de gozo temblorosa"
# El patrón describe un caracter con letras o números que terminen en rosa
# Uso del '+' en la siguiente sección *Repetición de patrones*
result = re.search('\w+rosa', texto)
print result.group()
result = re.findall('\w+rosa', texto)
print result
Expresiones regulares¶
Estas expresiones regulares hacen parte de un grupo de patrones básicos y su significado dentro de estos:
- \w : abecedario en letras minúsculas, los números naturales y el guión bajo [a-z, 0-9, _]. Para las letras mayúsculas se usa \W.
- . Cualquier carácter diferente a \n
- \s Carácter de espacio: \n nueva línea, \t tabulación.
- \d Números naturales.
- ^ reconoce el comienzo de un string
- $ reconoce el final de un string
- ? reconoce el fragmento de string con o sin el carácter a su izquierda
- {a} reconoce un fragmento con a repeticiones del carácter a su izquierda
- [abc] Indica un conjunto de posibles coincidencias, en este caso puede concidir con 'a', 'b' o 'c'
texto = u'En la memoria tendré presente el horrible día'
# El punto reconoce cualquier carácter excepto \n (nueva línea)
result = re.findall('.en', texto)
print result
# Cada punto agrega un nuevo caracter al segmento de string encontrado
result = re.findall('..en', texto)
# Note que en el primer segmento el nuevo carácter es un espacio
print result
# \s reconoce todo tipo de carácteres de espacio
result = re.findall('\shorrible', texto)
print result
# No se reconoce el fragmento 'ente' porque, a pesar de que esta presente
# en el texto, no está precedido por un espacio
result = re.findall('\sente', texto)
print result
texto = 'Ima Sumac'
# ^ Reconoce el inicio de un string
result = re.findall('^I..', texto)
print result
# $ reconoce el final de un string
result = re.findall('..c$', texto)
print result
Puede indicarse el fin del string sin decir exactamente algunos carácteres
result = re.findall('m..$', texto)
print result
texto = 'despiert o despierto'
# Encuentra el segmento de string con o sin la *o* que tiene el símbolo
result = re.findall('despierto?', texto)
print result
texto = "ABBDDDEAEEABDCCBDDC"
# Se busca un fragmento en el que la D se repita 3 veces y sea precedida de la letra B
result = re.findall('BD{3}', texto)
print result
También es posible dar un rango para el número de repeticiones
# Se busca un fragmento en el que la D se repita de 1 a 3 veces y sea precedida de la letra B
result = re.findall('BD{1,3}', texto)
print result
texto = 'Me gusta la pera pero como muchas manzanas'
# Encuentra fragmentos que comiencen en *per* y terminen en *a* o *o*
result = re.findall('per[ao]', texto)
print result
Repetición en los patrones¶
' + '¶
Reconoce 1 ó más repeticiones del caracter que se encuentre a la izquierda de este símbolo.
Si el patrón es 'm\w+', este busca la palabra que contenga una m y que seguida de esta hayan caracteres de tipo \w (a-z, 0-9, _). En este caso devuelve el string desde la m hasta un caracter que no sea de tipo \w
texto = "Hermann Melville"
# Se busca un string que comience por "He" y que le sigan caracteres de tipo \w
result = re.search('^He\w+', texto)
print result.group()
Hermann
# Se busca un string que termine en "lle" y que le antecedan caracteres de tipo \w
result = re.search('\w+lle$', texto)
print result.group()
Melville
' * '¶
Reconoce 0 ó más repeticiones del caracter que se encuentre a la izquierda
Si el patrón es 'AB', este reconoce 'A' y 'AB' con la cantidad de B* consecutivas que hayan en el string
texto = "ABBABDDDEAEECCC"
# Se busca un fragmento de string que sea A o que comience por A y sea seguido por B
result = re.findall('AB*', texto)
print result
['ABB', 'AB', 'A']
Combinaciones y generación de otros patrones¶
texto = 'La vida interior de Martin Frost'
result = re.findall('in*', texto)
print result
Pero al agregar ' ? ' al patrón el resultado será fragmentos de string que cumplan la condición pero con la menor longitud posible. En este caso el patrón ' in* ' encuentra ' i ' e ' i ' seguido de cuantos ' n ' haya en el string, por lo que al buscar con el patrón ' in*? ' el fragmento con menor longitud es ' i '. Se puede aplicar la misma lógica a comibaciones como ' +? ', '{a, b}? ' y ' ?? '.
result = re.findall('in*?', texto)
print result
texto = 'La vida interior de Martin Frost'
Encuentra un segmento de texto solo si es seguido por lo indicado en el paréntesis en este caso ' Frost'
result = re.findall('.+Martin(?= Frost)', texto)
print result
Lo contrario a lo anteriror es con el símbolo ' ! '. Encuentra en texto solo si no es seguido por lo indicado en el paréntesis
result = re.findall('.+Martin(?!Rogelio)', texto)
print result
También es posible encontrar fragmentos de un string indicando lo que le precede con esta sintaxis. En el paréntesis se indica que caracteres debe ir antes.
# Encuentra un string solo si es precedido por 'La '
result = re.findall('(?<=La )vida interior.+', texto)
print result
La negación es igualmente con el signo ' ! '
# Encuentra un string solo si no es precedido por 'La '
result = re.findall('(?<!La )vida interior.+', texto)
print result
Búsqueda de caracteres usados como patrón¶
Caracteres que no pueden ser usados como patrón, puesto que son reservados para describirlos:
- . ^ $ * + ? { [ ] \ | ( )
Para utilizar estos símbolos como parte de un patrón de búsqueda deben ser precedidos por el backslash " \ "
texto = "Qué es esto?"
print texto
Al buscar el caractér si el backslash la salida no corresponde al patrón buscado, puesto que este realiza la operación dada por ser una expresión regular.
result = re.search('o\?', texto)
print result.group()
sub¶
Este método permite sustituir fragmentos de un string mediante un patrón y una función. Por ejemplo en la frase "We die in proportion to the words we fling around us" Se reemplazarán las palabras que comiencen por la letra ' w ' o ' W ' por la misma palabra en mayúscula.
Se importa la librería locale y se especifica la región para que se reconoczca dentro de los patrones los caracteres especiales del español, como la ñ y las letras tildadas, como letras.
frase = "We die in proportion to the words we fling around us"
# se revisa primero con el método re.findall que el patrón seleccionado sea el correcto
re.findall('[wW]\w+', frase)
re.sub('[wW]\w+', lambda x: x.group().upper(), frase)
0 comments