Expresiones Regulares
Una expresión regular (abreviada como regex [...]) es una secuencia de caracteres que especifica un patrón de búsqueda en texto. [...] utilizada por algoritmos de búsqueda de cadenas para operaciones de "buscar" o "buscar y reemplazar" en cadenas, o para validación de entrada.
- Importe el módulo regex con
import re. - Cree un objeto Regex con la función
re.compile(). (Recuerde usar una cadena sin formato/raw string). - Pase la cadena que desea buscar al método
search()del objeto Regex. Esto devuelve un objetoMatch. - Llame al método
group()del objeto Match para devolver una cadena con el texto coincidente real.
Todas las funciones regex en Python están en el módulo re:
# Importar el módulo re para operaciones de expresiones regulares
import re
Símbolos Regex
| Símbolo | Coincide |
|---|---|
? | cero o una vez del grupo precedente. |
* | cero o más veces del grupo precedente. |
+ | una o más veces del grupo precedente. |
{n} | exactamente n veces del grupo precedente. |
{n,} | n o más veces del grupo precedente. |
{,m} | 0 a m veces del grupo precedente. |
{n,m} | al menos n y como máximo m veces del p precedente. |
{n,m}? o *? o +? | realiza una coincidencia no codiciosa (non-greedy) del p precedente. |
^spam | significa que la cadena debe comenzar con spam. |
spam$ | significa que la cadena debe terminar con spam. |
. | cualquier carácter, excepto los caracteres de nueva línea. |
\d, \w, y \s | un dígito, palabra o carácter de espacio, respectivamente. |
\D, \W, y \S | cualquier cosa excepto un dígito, palabra o espacio, respectivamente. |
[abc] | cualquier carácter entre los corchetes (como a, b, ). |
[^abc] | cualquier carácter que no esté entre los corchetes. |
Objetos Regex Coincidentes
# re.compile(): crear objeto de patrón regex (usar cadena sin formato r'' para evitar el escape)
phone_num_regex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d') # Patrón: 3 dígitos-3 dígitos-4 dígitos
mo = phone_num_regex.search('Mi número es 415-555-4242.') # Buscar patrón
print(f'Número de teléfono encontrado: {mo.group()}') # group() devuelve el texto coincidente
Phone number found: 415-555-4242
Agrupación con paréntesis
# Los paréntesis crean grupos: group(1) devuelve el primer grupo, group(2) devuelve el segundo
phone_num_regex = re.compile(r'(\d\d\d)-(\d\d\d-\d\d\d\d)') # Dos grupos entre paréntesis
mo = phone_num_regex.search('Mi número es 415-555-4242.')
mo.group(1) # Devuelve el primer grupo: '415'
'415'
mo.group(2)
'555-4242'
mo.group(0)
'415-555-4242'
mo.group()
'415-555-4242'
Inicia sesión para responder este quiz y rastrear tu progreso de aprendizaje
group() cuando se llama en un objeto de coincidencia?Para recuperar todos los grupos a la vez, use el método groups():
# groups(): devuelve una tupla de todos los grupos
mo.groups() # Devuelve ('415', '555-4242')
('415', '555-4242')
area_code, main_number = mo.groups()
print(area_code)
415
print(main_number)
555-4242
Múltiples grupos con Pipe
Puede usar el carácter | donde quiera hacer coincidir una de muchas expresiones.
hero_regex = re.compile (r'Batman|Tina Fey')
mo1 = hero_regex.search('Batman y Tina Fey.')
mo1.group()
'Batman'
mo2 = hero_regex.search('Tina Fey y Batman.')
mo2.group()
'Tina Fey'
También puede usar el pipe para hacer coincidir uno de varios patrones como parte de su regex:
bat_regex = re.compile(r'Bat(man|mobile|copter|bat)')
mo = bat_regex.search('Batmobile perdió una rueda')
mo.group()
'Batmobile'
mo.group(1)
'mobile'
Coincidencia opcional con el signo de Interrogación
El carácter ? marca el grupo que lo precede como una parte opcional del patrón.
bat_regex = re.compile(r'Bat(wo)?man')
mo1 = bat_regex.search('Las Aventuras de Batman')
mo1.group()
'Batman'
mo2 = bat_regex.search('Las Aventuras de Batwoman')
mo2.group()
'Batwoman'
Coincidencia de cero o más con el Asterisco
El * (asterisco) significa “coincidir cero o más veces”. El grupo que precede al asterisco puede aparecer cualquier número de veces en el texto.
bat_regex = re.compile(r'Bat(wo)*man')
mo1 = bat_regex.search('Las Aventuras de Batman')
mo1.group()
'Batman'
mo2 = bat_regex.search('Las Aventuras de Batwoman')
mo2.group()
'Batwoman'
mo3 = bat_regex.search('Las Aventuras de Batwowowowoman')
mo3.group()
'Batwowowowoman'
Coincidencia de uno o más con el Plus
El + (o plus) significa coincidir uno o más veces. El grupo que precede a un plus debe aparecer al menos una vez:
bat_regex = re.compile(r'Bat(wo)+man')
mo1 = bat_regex.search('Las Aventuras de Batwoman')
mo1.group()
'Batwoman'
mo2 = bat_regex.search('Las Aventuras de Batwowowowoman')
mo2.group()
'Batwowowowoman'
mo3 = bat_regex.search('Las Aventuras de Batman')
mo3 is None
True
Coincidencia de repeticiones específicas con Llaves
Si tiene un grupo que desea repetir un número específico de veces, siga el grupo en su regex con un número entre llaves:
ha_regex = re.compile(r'(Ha){3}')
mo1 = ha_regex.search('HaHaHa')
mo1.group()
'HaHaHa'
mo2 = ha_regex.search('Ha')
mo2 is None
True
En lugar de un número, puede especificar un rango con un mínimo y un máximo entre las llaves. Por ejemplo, la expresión regular (Ha){3,5} coincidirá con ‘HaHaHa’, ‘HaHaHaHa’ y ‘HaHaHaHaHa’.
ha_regex = re.compile(r'(Ha){2,3}')
mo1 = ha_regex.search('HaHaHaHa')
mo1.group()
'HaHaHa'
Coincidencia codiciosa (Greedy) y no codiciosa (Non-greedy)
Las expresiones regulares de Python son codiciosas por defecto: en situaciones ambiguas intentarán hacer coincidir la cadena más larga posible. La versión no codiciosa de las llaves, que coincide con la cadena más corta posible, tiene la llave de cierre seguida de un signo de interrogación.
greedy_ha_regex = re.compile(r'(Ha){3,5}')
mo1 = greedy_ha_regex.search('HaHaHaHaHa')
mo1.group()
'HaHaHaHaHa'
non_greedy_ha_regex = re.compile(r'(Ha){3,5}?')
mo2 = non_greedy_ha_regex.search('HaHaHaHaHa')
mo2.group()
'HaHaHa'
Inicia sesión para responder este quiz y rastrear tu progreso de aprendizaje
_ en lugar de +? después del cuantificador (ej. _?, +?, {3,5}?)El método findall()
El método findall() devolverá las cadenas de cada coincidencia en la cadena buscada.
phone_num_regex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d') # no tiene grupos
phone_num_regex.findall('Celular: 415-555-9999 Trabajo: 212-555-0000')
['415-555-9999', '212-555-0000']
Creando sus propias clases de caracteres
Puede definir su propia clase de caracteres usando corchetes. Por ejemplo, la clase de caracteres [aeiouAEIOU] coincidirá con cualquier vocal, tanto minúscula como mayúscula.
vowel_regex = re.compile(r'[aeiouAEIOU]')
vowel_regex.findall('Robocop come comida de bebé. COMIDA DE BEBÉ.')
['o', 'o', 'o', 'e', 'a', 'a', 'o', 'o', 'A', 'O', 'O']
También puede incluir rangos de letras o números usando un guion. Por ejemplo, la clase de caracteres [a-zA-Z0-9] coincidirá con todas las letras minúsculas, letras mayúsculas y números.
Al colocar un carácter circunflejo (^) justo después del corchete de apertura de la clase de caracteres, puede crear una clase de caracteres negativa que coincidirá con todos los caracteres que no están en la clase de caracteres:
consonant_regex = re.compile(r'[^aeiouAEIOU]')
consonant_regex.findall('Robocop come comida de bebé. COMIDA DE BEBÉ.')
['R', 'b', 'c', 'p', ' ', 't', 's', ' ', 'b', 'b', 'y', ' ', 'f', 'd', '.', ' ', 'B', 'B', 'Y', ' ', 'F', 'D', '.']
Los caracteres Caret y Dollar sign
También puede usar el símbolo de circunflejo
^al comienzo de una regex para indicar que una coincidencia debe ocurrir al principio del texto buscado.De manera similar, puede colocar un signo de dólar
$al final de la regex para indicar que la cadena debe terminar con este patrón regex.Y puede usar el
^y el$juntos para indicar que toda la cadena debe coincidir con la regex.
La cadena de expresión regular r'^Hello' coincide con las cadenas que comienzan con ‘Hello’:
begins_with_hello = re.compile(r'^Hello')
begins_with_hello.search('Hello mundo!')
<_sre.SRE_Match object; span=(0, 5), match='Hello'>
begins_with_hello.search('Él dijo hola.') is None
True
La cadena de expresión regular r'\d\$' coincide con cadenas que terminan con un carácter numérico del 0 al 9:
whole_string_is_num = re.compile(r'^\d+$')
whole_string_is_num.search('1234567890')
<_sre.SRE_Match object; span=(0, 10), match='1234567890'>
whole_string_is_num.search('12345xyz67890') is None
True
whole_string_is_num.search('12 34567890') is None
True
El carácter Comodín
El carácter . (o punto) en una expresión regular coincidirá con cualquier carácter excepto una nueva línea:
at_regex = re.compile(r'.at')
at_regex.findall('El gato en el sombrero se sentó en la alfombra plana.')
['cat', 'hat', 'sat', 'lat', 'mat']
Coincidencia de todo con Dot-Star
name_regex = re.compile(r'First Name: (.*) Last Name: (.*)')
mo = name_regex.search('First Name: Al Last Name: Sweigart')
mo.group(1)
'Al'
mo.group(2)
'Sweigart'
El .* usa el modo codicioso (greedy): Siempre intentará hacer coincidir la mayor cantidad de texto posible. Para hacer coincidir cualquier y todo el texto de manera no codiciosa, use el punto, el asterisco y el signo de interrogación (.*?). El signo de interrogación le dice a Python que coincida de manera no codiciosa:
non_greedy_regex = re.compile(r'<.*?>')
mo = non_greedy_regex.search('<Servir al hombre> para la cena.>')
mo.group()
'<To serve man>'
greedy_regex = re.compile(r'<.*>')
mo = greedy_regex.search('<Servir al hombre> para la cena.>')
mo.group()
'<To serve man> for dinner.>'
Coincidencia de nuevas líneas con el carácter Punto
El punto-asterisco coincide con todo excepto una nueva línea. Al pasar re.DOTALL como segundo argumento a re.compile(), puede hacer que el carácter punto coincida con todos los caracteres, incluido el carácter de nueva línea:
no_newline_regex = re.compile('.*')
no_newline_regex.search('Sirva la confianza pública.\nProteja al inocente.\nMantenga la ley.').group()
'Serve the public trust.'
newline_regex = re.compile('.*', re.DOTALL)
newline_regex.search('Sirva la confianza pública.\nProteja al inocente.\nMantenga la ley.').group()
'Serve the public trust.\nProtect the innocent.\nUphold the law.'
Coincidencia sin distinción entre mayúsculas y minúsculas
Para hacer que su regex no distinga entre mayúsculas y minúsculas, puede pasar re.IGNORECASE o re.I como segundo argumento a re.compile():
robocop = re.compile(r'robocop', re.I)
robocop.search('Robocop es parte hombre, parte máquina, todo policía.').group()
'Robocop'
robocop.search('ROBOCOP protege a los inocentes.').group()
'ROBOCOP'
robocop.search('Al, ¿por qué tu libro de programación habla tanto de robocop?').group()
'robocop'
Sustitución de cadenas con el método sub()
El método sub() para objetos Regex recibe dos argumentos:
- El primer argumento es una cadena para reemplazar cualquier coincidencia.
- El segundo es la cadena para la expresión regular.
El método sub() devuelve una cadena con las sustituciones aplicadas:
names_regex = re.compile(r'Agent \w+')
names_regex.sub('CENSURADO', 'El Agente Alice dio los documentos secretos al Agente Bob.')
'CENSORED gave the secret documents to CENSORED.'
Inicia sesión para responder este quiz y rastrear tu progreso de aprendizaje
sub()?Gestión de Regexes complejas
Para indicarle a la función re.compile() que ignore los espacios en blanco y los comentarios dentro de la cadena de expresión regular, se puede habilitar el “modo detallado” (verbose mode) pasando la variable re.VERBOSE como segundo argumento a re.compile().
Ahora, en lugar de una expresión regular difícil de leer como esta:
phone_regex = re.compile(r'((\d{3}|\(\d{3}\))?(\s|-|\.)?\d{3}(\s|-|\.)\d{4}(\s*(ext|x|ext.)\s*\d{2,5})?)')
puede distribuir la expresión regular en varias líneas con comentarios como este:
phone_regex = re.compile(r'''(
(\d{3}|\(\d{3}\))? # código de área
(\s|-|\.)? # separador
\d{3} # primeros 3 dígitos
(\s|-|\.) # separador
\d{4} # últimos 4 dígitos
(\s*(ext|x|ext.)\s*\d{2,5})? # extensión
)''', re.VERBOSE)
Inicia sesión para responder este quiz y rastrear tu progreso de aprendizaje
re.VERBOSE cuando se pasa a re.compile()?