Uma expressão regular (regexp) é uma forma concisa e flexível de definir padrões (máscaras) a serem identificados em sequências de caracteres (Strings).
# Utilizar o módulo de expressões regulares (re)
import re
Suponha que queiramos verificar se uma pessoa digitou um número de CPF que seja sintaticamente correto. Como sabemos, os números de CPF são compostos por 11 dígitos numéricos. Assim, podemos definir um padrão como:
"[0-9]{11}"
Nesta expressão regular temos:
cpf = input("Digite seu número de CPF: ")
padrao_cpf = '[0-9]{11}'
if re.match(padrao_cpf, cpf):
print("CPF ok")
else:
print("CPF com problemas")
Note que se você digitar algo como "12345678901234afasdf", o resultado será "CPF ok", apesar de nitidamente vermos que isso não parece correto. Tal fato ocorre em Python porque a função match procura pelo padrão a partir do início da string. Como o valor digitado inicia com 11 dígitos numéricos, o padrão definido pela expressão regular está presente no valor digitado, de forma que o valor digitado condiz com o padrão, apesar de ser seguido por outros caracteres. Para corrigir isso, é necessário ajustar a expressão regular, incluindo o caracter "$" no final:
"[0-9]{11}$"
O uso do caracter "$" indica que no valor digitado não deve haver mais nenhum caracter após a parte que condiz com o padrão.
# A expressão regular inclui o caracter "$" no final
cpf = input("Digite seu número de CPF: ")
padrao_cpf = '[0-9]{11}$'
if re.match(padrao_cpf, cpf):
print("CPF ok")
else:
print("CPF com problemas")
O padrão acima considera que o CPF tenha apenas dígitos numérico. Se o CPF for digitado sem seu formato habitual (ex: "123.456.789-01") o reconhecimento falhará visto que a expressão regular não prevê o uso de pontos e hífen. Um novo ajuste é necessário caso queiramos que este padrão seja reconhecido. Algo como:
"[0-9]{3}\.?[0-9]{3}\.?[0-9]{3}-?[0-9]{2}$"
# Expressão regular que reconhece pontos e hífen no CPF
cpf = input("Digite seu número de CPF: ")
padrao_cpf = r'[0-9]{3}\.?[0-9]{3}\.?[0-9]{3}-?[0-9]{2}$'
if re.match(padrao_cpf, cpf):
print("CPF ok")
else:
print("CPF com problemas")
Note que o caracter "." foi precedido por uma contrabarra "\" na expressão regular. Isto é necessário pois o caracter ponto tem semântica específica em expressões regulares, significando "qualquer caracter". Assim, a expressão ".{5}" significa quaisquer cinco caracteres. Mas no nosso caso, nós queremos que seja de fato o ponto, e não um caracter qualquer. Para garantir esta interpretação é necessário precedê-lo por uma contrabarra.
Mas ao inserir a contrabarra nós acabamos gerando um conflito. Acontece que em Python a contrabarra já é utilizada em strings para identificar caracteres particulares. Por exemplo, na string "uma linha\noutra linha" a sequência "\n" indica uma quebra de linha (new line) (veja outros caracteres especiais). De forma a evitar esta dupla interpretação da contrabarra (em Python e na expressãor regular) é que sugere-se que as strings correspondentes à expressão regulares sejam precedidas da letra "r", significando raw string, ou seja, que as contrabarras não serão interpretadas pela linguagem Python, mas apenas pelo interpretador de expressões regulares.
O carater "?" inserido após os pontos e o hífen é outro modificador, indicando que o que vem antes pode ocorrer 0 (zero) ou 1 (uma) vez, mas não mais. Desta forma a expressão regular reconhece CPFs com ou sem pontos e hífen.
Outro exemplo do uso de expressões regulares é o reconhecimento de endereços eletrônicos (e-mail). No caso da UFSC, os endereços de email tem formatos como:
Abaixo é apresentado uma expressão regular que permite identificar estes padrões.
# Expressão regular que reconhece e-mail UFSC
email = input("Digite seu endereço eletrônico: ")
padrao_email = r'[a-z][a-z.]+@([a-z]+\.)*ufsc\.br$'
if re.match(padrao_email, email):
print("É um e-mail UFSC")
else:
print("Não é um e-mail UFSC válido")
O padrão:
r'[a-z][a-z.]+@([a-z]+\.)*ufsc.br$'
indica que os endereços eletrônicos devem:
Além de reconhecimento de padrões, as expressões regulares podem ser utilizadas para separar partes de uma string. Para exemplificar, considere que polinômio: $-4x^5-x^4+2x$ que pode ser representado pela string: "-4x5-x4+2x". Podemos identificar e separar seus termos utilizando o método findall, conform exemplificado abaixo.
# Identificação dos termos de um polinômio
padrao_termo = r'[-+0-9]*x[0-9]*'
polinomio = '-4x5-x4+2x'
termos = re.findall(padrao_termo, polinomio)
print(termos)
O mecanismo acima corretamente identifica os termos do polinômio (resultando numa lista), mas falha no caso do polinômio: $-4x^5-x^4+2x-10$ uma vez que o último termo não inclui a variável "x": o último termo não é identificado. Para identificá-lo é necessário alterar a expressão regular, a exemplo do descrito abaixo.
# Identificação dos termos de um polinômio
padrao_termo = r'[-+0-9]*x[0-9]*|[-+0-9]+'
polinomio = '-4x5-x4+2x-10'
termos = re.findall(padrao_termo, polinomio)
print(termos)
Na expressão regular foi incluída no final a sequência "|[-+0-9]+" sendo que a barra vertical "|" corresponde a um OU lógico, ou seja, passam a ser reconhecidos o padrão à sua esquerda ou o padrão à sua direita.
Observe abaixo que foram incluídos pares de parênteses em torno das partes da expressão que reconhecem os coeficientes e os expoentes dos termos dos polinômios. Como resultado, o método findall não apenas reconhece os termos, mas também já os separa retornando-os na forma de tuplas.
# Identificação dos coeficientes e expoentes dos termos de um polinômio
padrao_termo = r'([-+0-9]*)x([0-9]*)|([-+0-9]+)'
polinomio = '-4x5-x4+2x-10'
termos = re.findall(padrao_termo, polinomio)
print(termos)
A lista de métodos para operar com expressões regulares inclui: