Mostrando las entradas con la etiqueta expresiones regulares. Mostrar todas las entradas
Mostrando las entradas con la etiqueta expresiones regulares. Mostrar todas las entradas

lunes, 1 de septiembre de 2014

EXPRESIONES REGULARES EN PYTHON(II)

METACARACTERES Y PATRONES
Son símbolos que indican un comportamiento especial como repetición, rango, exclusión o separación.
. ^ $ * + ? { } [ ] \ | ( )

.
Indica cualquier carácter (letras, números, signos de puntuación, espacios) excepto una nueva línea (\n):
>>> re.findall('.', 'Benevolent dictator')
['B', 'e', 'n', 'e', 'v', 'o', 'l', 'e', 'n', 't', ' ', 'd', 'i', 'c', 't', 'a', 't', 'o', 'r']

>>> re.findall('.', 'Benevolent\ndictator') #Ignora la nueva línea (\n)
['B', 'e', 'n', 'e', 'v', 'o', 'l', 'e', 'n', 't', 'd', 'i', 'c', 't', 'a', 't', 'o', 'r']


>>> re.findall('.', 'Benevolent\tdictator') #Pero no ignora la tabulación (\t)
['B', 'e', 'n', 'e', 'v', 'o', 'l', 'e', 'n', 't', '\t', 'd', 'i', 'c', 't', 'a', 't', 'o', 'r']


*
Tiene en cuenta el carácter anterior cero o más veces. Por ejemplo, el patrón "in*o" identifica estas combinaciones: io (ninguna presencia de la "n"), ino (una aparición de la "n"), inno (dos apariciones de la "n").
>>> re.findall('in*o', 'inocencia, innovaciones')
['ino', 'inno', 'io']


+
Indica el carácter anterior una o más veces:
>>> re.findall('in+o', 'inocencia, innovaciones')
['ino', 'inno']


[ ]
Indica que puede haber una coincidencia con cualquier carácter entre los corchetes. También se puede incluir el rango entre los corchetes:
[a-z] : cualquier letra minúscula
[0-9] : cualquier dígito
[a-dA-D] : las letras de la a la d minúsculas o mayúsculas

>>> re.findall('cu[sz]co', 'se puede escribir cusco o cuzco')
['cuzco', 'cusco']

Se puede señalar un rango usando guión. Por ejemplo, [0-9] busca cualquier dígito entre 0 y 9.

>>> re.findall('[0-9]', '3 de enero de 2014')
['3'] # el único con una sola cifra

[^ ]
Busca cualquier caracter excepto el indicado en corchetes

>>> re.findall('est[^a]s', 'estas, estos, estes')
['estos', 'estes']

{ n }
Repite el elemento previo n veces. Se puede definir un rango de coincidencias

{2,4} : de 2 a 4 caracteres siendo el comportamiento "voraz", es decir, primero trata de hacer coincidir cuatro caracteres, luego tres, luego dos.
{2,} : indica dos o más caracteres.

>>> re.findall('[a-z]{3}', 'Django es un framework de desarrollo web')
['jan', 'fra', 'mew', 'ork', 'des', 'arr', 'oll', 'web']

>>> re.findall('[a-z]{3,4}', 'Django es un framework de desarrollo web')
['jang', 'fram', 'ewor', 'desa', 'rrol', 'web']

>>> re.findall('[a-z]{3,}', 'Django es un framework de desarrollo web')
['jango', 'framework', 'desarrollo', 'web']


^ $
Buscan al comienzo y al final de la cadena de texto respectivamente.
>>> re.findall('^Django', 'Django es un framework de desarrollo web')
['Django']

>>> re.findall('^web', 'Django es un framework de desarrollo web')
[]  # 'web' no está al comienzo de la cadena

>>> re.findall('web$', 'Django es un framework de desarrollo web')
['web']  # 'web' está al final de la cadena


?
Busca una o cero coincidencias del caracter anterior.
i?python : busca python o ipython.
>>> re.findall('i?python', 'ipython es iron python')
['ipython', 'python']

\
Permite ignorar caracteres especiales como [], ?, +, etc. Por ejemplo, si queremos analizar operaciones matemáticas debemos ignorar el significado de + y * en el módulo de expresiones regulares:
>>> re.split(' \+ ', '4 + 8') #Queremos extraer sólo los números
['4', '8']

|
Identifica un patrón u otro siendo su comportamiento "no voraz (not greedy)", es decir, al encontrar la coincidencia de la izquierda se detiene. Por ejemplo, queremos sustituir un anglicismo:
>>> re.sub('basket|basketball', 'baloncesto', 'Jugadores de basketball de la liga nacional de basket') #Encuentra basketball y lo sustituye por baloncestoball
'Jugadores de baloncestoball de la liga nacional de baloncesto'

Para corregir este comportamiento simplemente colocamos el más largo primero:
>>> re.sub('basketball|basket', 'baloncesto', 'Jugadores de basketball de la liga nacional de basket')
'Jugadores de baloncesto de la liga nacional de baloncesto'


()
Los paréntesis agrupan expresiones regulares e indican el comienzo y el final de un grupo. Findall agrupa las coincidencias en tuplas:

>>> re.findall(r"(\w+): (\w+)", "nombre: Gabriel, apellido: Marquez, numero: 3")
[('nombre', 'Gabriel'), ('apellido', 'Marquez'), ('numero', '3')]



(?:)

 Agrupa expresiones regulares pero no captura coincidencias. Esto es más evidente al usar split:
>>> re.split(r"(?:\w+):", "nombre: Gabriel, apellido: Marquez, numero: 3")
['', ' Gabriel, ', ' Marquez, ', ' 3']


Comparemos al usar sólo paréntesis:
>>> re.split(r"(\w+):", "nombre: Gabriel, apellido: Marquez, numero: 3")
['', 'nombre', ' Gabriel, ', 'apellido', ' Marquez, ', 'numero', ' 3']


(?P:<>)

Agrupa coincidencias que pueden ser referenciadas por un nombre:
>>> patron = r'(?P<mes>[\d])/(?P<dia>[\d])/(?P<año>[0-9][0-9][0-9][0-9])'
>>> m = re.search(patron, 'nacio en 7/2/1978')

>>> m.group('año')
'1978'
>>> m.group('mes')
'7'
>>> m.group('dia')
'2'

Un ejemplo de la página del tutorial de django:
urlpatterns = [
    # ex: /polls/
    url(r'^$', views.index, name='index'),
    # ex: /polls/5/
    url(r'^(?P[0-9]+)/$', views.detail, name='detail'),
    # ex: /polls/5/results/
    url(r'^(?P[0-9]+)/results/$', views.results, name='results'),
    # ex: /polls/5/vote/
    url(r'^(?P[0-9]+)/vote/$', views.vote, name='vote'),
]

miércoles, 23 de julio de 2014

EXPRESIONES REGULARES EN PYTHON(I)

Las expresiones regulares son como pequeños lenguajes de programación y cuando se trata de procesar cadenas de texto resultan ser herramientas convenientes. Lo primero que hacemos en Python para trabajar con expresiones regulares es invocar al módulo:

>>> import re

Algunas funciones de este módulo son: compile, match, search, findall, split, sub, finditer.

COMPILE
Prepara el patrón de caracteres que se va a buscar. La sintaxis de compile es:

>>> re.compile(pattern, flags=0)

pattern es el patrón de caracteres que se va a buscar y flags es el modificador que cambia el comportamiento del patrón. Esto es lo que hace cada modificador que aplicamos en compile.

FLAGS:
re.IGNORECASE (re.I) no distingue entre mayúsculas y minúsculas.
re.LOCALE (re.L) permite que algunos caracteres especiales tengan en cuenta el idioma que se usa en el computador local.
re.MULTILINE (re.M) permite que "^" busque el comienzo de cada linea (no solo el comienzo del texto) y que "$" busque el final de cada linea (no solo el final del texto).
re.DOTALL (re.S) hace que "." busque cualquier caracter incluyendo una nueva linea (es decir '\n').
re.UNICODE (re.U) permite usar caracteres Unicode.
re.VERBOSE (re.X) se utiliza para poder dividir una expresión regular compleja en pequeños fragmentos que pueden tener comentarios para una mejor comprensión.
Si no se desea compilar pero sí usar modificadores, se puede usar el símbolo (?_) junto con uno o varios modificadores, por ejemplo, (?i), (?m), (?iL).
A parte de la opción de usar modificadores compile ofrece una ligera mayor velocidad de búsqueda de los caracteres correspondientes. Un ejemplo de uso de compile:

>>> pattern = re.compile('python', re.I)
>>> pattern.findall('la programación PyThOn')
['PyThOn']

Aqui con re.I se ignoran las mayúsculas y minúsculas lo que se puede lograr también sin compilar usando (?i):

>>> re.findall('(?i)python','la programacion PyThOn')
['PyThOn']

De otra forma no hay correspondencia:

>>> re.findall('python','la programacion Python')
[]

MATCH
La función match determina si hay una coincidencia únicamente al comienzo del texto procesado:

>>> patron = "Python"
>>> texto1 = "Monty Python"
>>> texto2 = "Python interpreter"
>>> match1 = re.match(patron, texto1)
>>> type(match1)  # no hay coincidencia
<type 'NoneType'>
>>> print match1
None
>>> match2 = re.match(patron, texto2)
<_sre.SRE_Match object at 0x02A2DF00>
>>> match.group() # hay una coincidencia
'Python'

Incluso si se usa el modificador MULTILINE solamente hay búsqueda al comienzo del texto.

>>> texto3 = "Monty \n Python"
>>> match3 = re.match(patron, texto3, re.M)#no hay coincidencia


SEARCH
Busca la primera aparición del patrón de búsqueda en la cadena de texto. Search devuelve un objeto match o None si no hay coincidencia. El método group() devuelve el texto coincidente.

>>> match = re.search('django', 'plataforma django, django reinhardt')
>>> match.group()
'django'

Search sólo devuelve la primera coincidencia. Para comprobarlo podemos usar match.span() que indica dónde comienza y termina el texto encontrado.

>>> match.span()
(11, 17)


FINDALL
Encuentra todas las coincidencias en forma de lista:

>>> re.findall('\d+', '23 de junio, 14 de mayo')
['23', '14']

FINDITER
Devuelve un iterador de objetos match. El resultado es igual a findall pero generando los elementos de la lista uno por uno.

>>> iter = re.finditer('\d+', '23 de junio, 14 de mayo')
>>> iter
<callable-iterator object at 0x02ACE610>
>>> iter.next()
<_sre.SRE_Match object at 0x02AD0528>
>>> iter.next().group()
'14'

SUB
Sustituye el patrón por La sintaxis de sub es:
>>> re.sub(patternreplstringcount=0flags=0)

>>> re.sub('string', 'cadena', 'remplaza la string de caracteres')
'remplaza la cadena de caracteres'

Count indica las veces que se debe sustituir el patrón de caracteres, por defecto se remplazan todas las apariciones del texto.

>>> re.sub('string', 'cadena', 'remplaza la string de caracteres string', count=1)
'remplaza la cadena de caracteres string'

Subn hace lo mismo pero devuelve una tupla con el número de remplazos.

>>> re.subn('string', 'cadena', 'remplaza la string de caracteres string')
('remplaza la cadena de caracteres cadena', 2)

SPLIT
Separa la cadena de texto en donde aparece el patrón.
>>> re.split(patternstringmaxsplit=0flags=0)

>>> re.split('web','Django es un framework web de codigo abierto escrito en Python')
['Django es un framework ', ' de codigo abierto escrito en Python']

lunes, 24 de febrero de 2014

PYTHON, UNICODE Y EXPRESIONES REGULARES

Una expresión regular es una forma de describir un conjunto de cadenas de texto. En Python se debe llamar al modulo re para buscar o remplazar patrones de texto. La función que busca todas las coincidencias es re.findall(patrón,texto,marcador). He aquí algunos ejemplos:




import re
print re.findall('reg','expresion regular')
print re.findall('201\d','2008, 2009, 2010, 2011')
print re.findall('\w+','expresion regular')

Salida:

['reg']
['2010', '2011']
['expresion', 'regular']
El patrón '\w+' corresponde a cualquier cantidad de letras sin incluir espacios vacíos. '201\d' corresponde a un número de cuatro cifras que comienza con 201. Más información acerca de expresiones regulares se puede encontrar en los siguientes vínculos:



En inglés es suficiente la codificación ASCII, pero en español para representar la eñe y las tildes es necesario la codificación Unicode. En un archivo Python hay que declarar Unicode al comienzo de la siguiente forma:

# -*- coding: UTF-8 -*-
En el siguiente ejemplo todavía no se reconoce la ó como una letra válida:
# -*- coding: UTF-8 -*-
import re
print re.findall('\w+','expresión regular')


Salida:

['expresi', 'n', 'regular']

De modo que especificamos el marcador (flag) re.UNICODE para que se tengan en cuenta los caracteres Unicode:

# -*- coding: UTF-8 -*-
import re
print re.findall('\w+','expresión regular',re.UNICODE)


Salida:

['expresi\xc3\xb3n', 'regular']
La ó aparece con su código Unicode, pero aparece normalmente con la función print:

lista = re.findall('\w+','expresión regular',re.UNICODE)
print lista
for item in lista:
    print item


Salida:

['expresi\xc3\xb3n', 'regular']
expresión
regular