Expressões regulares

Introdução

O conceito de expressão regular é um dos conceitos teóricos mais importantes de Computação, e também é muito usado na prática, em diversos tipos de atividades, como:

  • Encontrar um arquivo no seu computador cujo texto contenha um determinado padrão. Por exemplo, encontrar todos os arquivos em um determinado diretório que contenham um número de CPF ou CNPJ.
  • Verificar informações fornecidas por usuários que devem obeceder a formatos específicos, como números de telefone, endereços de email, CPF, RG, CEP, etc;
  • Verificar se um determinado trecho de código é sintaticamente correto, isso é, se obedece à sintaxe da linguagem de programação em que foi escrito;
  • Efetuar substituições de texto em um ou mais arquivos, caso o conteúdo obedeca um determinado padrão. Por exemplo substuir todas as ocorrências de "pcs", "psi" e "pea" em um conjunto de arquivos por "PCS", "PSI" e "PEA", respectivamente;
  • Extrair informações em páginas da Web. Por exemplo, capturar os preços de produtos em uma página de busca do Buscapé.

O termo "expressão regular" também é conhecido por regex ou regexp (contração do termo em Inglês, regular expression).

Você pode pensar em uma expressão regular como um "padrão" ou uma "forma" que é usada para generalizar e descrever um conjunto de strings (sequências de caracteres) sem precisar listar cada string individualmente.

Por exemplo, digamos que você queira encontrar todos os números de CPF em um texto. Como o número de strings que representam CPFs é muito grande para listar um por um, você pode usar uma expressão regular que se "encaixe" em qualquer número de CPF, como este:

<NUM><NUM><NUM><PONTO><NUM><NUM><NUM><PONTO><NUM><NUM><NUM><TRAÇO><NUM><NUM>

Onde: - <NUM> é qualquer dígito entre 0 e 9; - <PONTO> é o caractere de um ponto (.); - <TRAÇO> é o caractere de hífen (-);

Qualquer CPF válido e pontuado obedecerá ao padrão definido acima.

Outro exemplo: um padrão para encontrar números de telefone, sem considerar o DDD. Telefones móveis têm 9 dígitos, enquanto telefones fixos têm 8. Um possível padrão seria:

<NUM_OPCIONAL><NUMx4>-<NUMx4>

Onde: - <NUM_OPCIONAL> é qualquer dígito ou a string vazia; - <NUMx4> é uma sequência de 4 dígitos quaisquer; - O traço (-) representa ele mesmo.

Sintaxe

Como você pode ver, não basta conseguir definir o seu termo de busca como um padrão. Precisamos definir uma sintaxe (um formato) para esses padrões. Vamos usar <TRAÇO> ou - para definir um hífen? Vamos usar <NUM> várias vezes ou poderemos escrever coisas como <NUMx10> quando quisermos especificar sequências do mesmo tipo de caractere?

Quase todas as linguagens e ferramentas que suportam o uso de expressões regulares utilizam a mesma sintaxe e, para poder usar expressões regulares no seu dia-a-dia, você também precisa conhecê-la.

A tabela abaixo é uma referência resumida dessa sintaxe (veja outras referências, mais completas, na seção Recursos Adicionais).

Referência

Significado Exemplo Strings válidas Strings inválidas
caractere comum Qualquer caractere que não seja especial corresponde a ele mesmo. Os caracteres especiais são: {}[]()^$.|*+?\ e -, quando aparece dentro de colchetes ([]). frio
  • frio
  • Hoje está frio. (a regex pode aparecer em qualquer posição da string que está sob análise)
  • Você prefere frio ou calor?
  • Frio (regexes são, por padrão, case-sensitive)
  • fr-io
. Corresponde a qualquer caractere, com exceção do \n m.r
  • mar
  • amor
  • Que horas vamos comer?
  • semear
? O caractere ou grupo precedente é opcional (i.e., pode estar presente ou ausente). carro?
  • carro
  • carr
  • carros
  • carroça
* Especifica que o caractere ou grupo que precede o `*` deve aparecer 0 ou mais vezes. ba*
  • b
  • ba
  • baa
  • baaaaaaaaaaa
  • a
+ Especifica que o caractere ou grupo que precede o `+` deve aparecer 1 ou mais vezes. ba+
  • ba
  • baa
  • baaaaaaaaaaa
  • b
  • a
{n} Especifica que o caractere ou grupo que precedente deve aparecer exatamente `n` vezes. ba{3}
  • baaa
  • b
  • ba
  • baaaa
| Especifica conjunção (`OR`). ba(nana|rraca)
  • banana
  • barraca
  • ba
[abc123] Colchetes são usados para definir opções. Um grupo entre colchetes corresponde a qualquer um (e apenas um) dos caracteres especificados entre os colchetes. [2345]
  • 2 itens
  • 3 itens
  • 24 itens
\d Corresponde a qualquer dígito. Equivalente a `[0-9]`. \d
  • 0 itens
  • 9 itens
  • 0 itens
  • 9 itens
\s Corresponde a espaços em branco (` `, `\t`, `\n`). a\s
  • a b
  • ab
^ Corresponde ao início da string, ou início de uma linha, caso o texto tenha múltiplas linhas. ^v
  • você tem quantos anos?
  • quantos anos você tem?
$ Corresponde ao final da string, ou final de uma linha, caso o texto tenha múltiplas linhas. !$
  • Olá!
  • Tudo bem?!
  • Olá.
() Parênteses são usados tanto para agrupamento quanto para captura. ba(na){2}
  • banana
  • bananada
  • Doce de banana é bom.
  • abanar
  • cabana
Observação: para escrever uma expressão regular que reconheça caracteres que normalmente teriam um significado especial (e.g., ., ?, (, ), $), basta escapar estes caracteres com uma barra invertida, \. Por exemplo: a expressão que horas são\? reconheceria a string "Pode me dizer que horas são?", porque o ponto de interrogação está devidamente escapado.

Uso prático de expressões regulares

Muitas linguagens de programação e ferramentas possuem suporte à interpretação de expressões regulares. A maioria das linguagens de programação populares possui mecanismos nativos para a manipulação e uso de expressões regulares. Além disso, muitas ferramentas de linha de comando, como find, grep, sed e awk são comumente usadas com regexes.

O conceito de expressão regular é muito poderoso e é uma ferramenta essencial para resolver diversos problemas práticos. Por outro lado, para alguns problemas, a expressão regular correta pode ser bastante complexa e, sem a devida documentação, impossível de ser compreendida mais tarde—veja este exemplo da expressão regular oficial para reconhecer endereços de email em diversas linguagens.

Para encerrar, uma citação de Jamie Zawinski, co-fundador do Netscape e do Mozilla:

Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.

Exercícios

Escreva expressões regulares para reconhecer os padrões descritos abaixo. Leia o enunciado até o final antes de começar.

Número do exercício Descrição Exemplos válidos Exemplos inválidos
2.1 Um número USP, sem traços, pontos ou qualquer sinal de pontuação entre os dígitos.
  • 7581993
  • Meu número USP é: 6418542.
  • 7581-993
2.2 Número de telefone (fixo ou celular), com DDD entre parênteses, código do país precedido por "+" e espaços. Sem traços.
  • +55 (11) 999994321
  • +55 (51) 36975544
  • 55 (11) 99999
  • +55 (11) 9-9999-4321
2.3 Linhas de um arquivo que começam com um número de até dois dígitos, seguido por parênteses e por uma frase qualquer. A linha deve terminar com um ponto de interrogação.
  • 1) Qual o seu nome?
  • 01) Qual o seu nome? E a sua idade?
  • 01) Escreva o seu nome.
  • (01) Escreva o seu nome.
2.4 Um nome próprio, com as seguintes restrições:
  • No mínimo 2 nomes (nome e sobrenome) e no máximo 3.
  • Todos os nomes devem começar com letra maiúscula (e este é o único lugar em que letras maiúsculas podem aparecer)
  • O nome do meio, se presente, pode ser abreviado. A abreviação é a primeira letra do nome (maiúscula) seguida por um ponto
  • Todos os nomes devem ter pelo menos 3 letras (a não ser que seja o nome do meio abreviado)
  • Alan Mathison Turing
  • Ada Lovelace
  • Richard M. Stallman
  • turing
  • richie stallman
  • LinuS Torvalds
  • Edsger-Dijkstra
  • Ed Dijkstra

Observações

  • Nenhum destes exercícios tem uma resposta única. Dado um determinado padrão, é comum que existam várias expressões regulares que o reconheçam. Por exemplo, uma sequência de dois dígitos pode ser definida pelas expressões \d\d, \d{2}, [0-9]{2}, [0123456789][0123456789], etc.
  • Você pode usar o site regex101 para testar e entender suas expressões regulares. Utilize os exemplos válidos e inválidos fornecidos no enunciado, e escreva a sua expressão lá, até ficar satisfeito com o resultado.

Entrega

Entregar um arquivo zip com nome lab2-atv4-XXXXXX.zip contendo um único arquivo chamado regex.txt.

O arquivo deve conter uma linha para cada exercício da tabela acima, começando com o número do exercício, seguido de parênteses ()), 1 espaço e a expressão regular que você criou para resolver o problema.

Exemplo:

2.1) \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b
2.2) (19|20)\d\d
2.3) ^\s*#.*$
2.4) /\*.*?\*/



Última atualização: segunda-feira, 16 jan. 2017, 16:26