Expressões Regulares (ou RegEx), em um breve resumo, servem para representar padrões em strings, seja para validar uma entrada, verificar se um conteúdo existe na string ou um replace mais dinâmico. Esteticamente, uma RegEx não agrada aos olhos e muitas pessoas desenvolvedoras possuem um certo receio em alterar a RegEx, e até mesmo um bloqueio para aprender a trabalhar com as expressões regulares, mas olhando de perto, ela nem assusta tanto!
Antes de começar a falar de expressões regulares, vamos usar uma colinha básica. Vou colocar apenas os recursos que eu uso com mais frequência, e que já quebram um galhão!
Por enquanto, não é necessário entender como cada um dos itens abaixo é usado, isso nós iremos ver mais na frente.
Metacaracteres e seus significados
Metacaractere |
Significado |
\d | Dígito decimal |
[…] | Os [ ] representam um conjunto de caracteres |
[0-9] | Mesma coisa que \d, porém representado com conjunto de caracteres |
\D | Caractere que NÃO seja um dígito, o oposto do \d |
[^…] | O ^ no conjunto nega tudo que tem dentro dele, ou seja, qualquer caractere fora do conjunto |
[^0-9] | Mesma coisa que \D, porém representado com a negação do conjunto |
\w | Caractere alfanumérico, também inclui o _. Igual a [0-9a-zA-Z_] |
\W | Caractere NÃO alfanumérico, o oposto de \w, ou seja: [^0-9a-zA-Z_] |
\s | Um espaço em branco. Mas cuidado, muitas vezes é confundido apenas pelo espaço, mas também representa nova linha, tabulação, retorno de carrinho, etc. O mesmo que [ \t\n\r\f\v] |
\S | Exatamente o contrário do \s, tudo que não for espaço em branco. O mesmo que [^ \t\n\r\f\v] |
\ | Escape, ele serve para colocar caracteres visto como parte da expressão como se fosse string. Exemplo, para colocar ^ e esperar exatamente o acento circunflexo, seria \^ |
\n | Quebra de linha |
. | QUALQUER caractere, exceto quebra de linha |
{n} | Quantidade esperada de caracteres. Exemplo: se esperamos 5 dígitos, podemos usar \d{5} |
{n,n2} | Quantidade de caracteres dentro de um range. Exemplo: se esperamos de 3 a 5 dígitos podemos usar \d{3,5} |
{n,} |
Quantidade MÍNIMA de caracteres. Exemplo: \d{3,} Essa expressão aceita 123, 1234, 111, 111111, qualquer número de no mínimo 3 dígitos. |
{,n} |
Quantidade MÁXIMA de caracteres. Exemplo: \d{,3} Essa expressão aceita 123, 12, 1, mas nada além de 3 dígitos, como 1234 |
+ |
Uma ou mais ocorrências, o mesmo que {1,}. Exemplo da expressão \w+ Aceita qualquer caractere alfanumérico, mas precisa ter no mínimo um caso. Casos aceitos: teste, 1234, qwe123,… |
? | Condicional de ocorrência. É o mesmo que {,1} |
* |
0 ou mais ocorrências. Exemplo de \d* Essa expressão aceita qualquer número mas também aceita estar vazia de dígitos |
^ |
Êpa, já vimos? Não! 🙂 Fora do conjunto de caracteres, o circunflexo representa início de texto ou linha |
$ | O oposto do ^, representa que esperamos o final da string ou linha |
(…) | Grupo, serve para agrupar parte do match na expressão regular, normalmente usado em replaces |
…|… | Operador OR, o | serve para considerar os dois lados como opções válidas para o match |
Não é só isso, dentro da RegEx nós também podemos usar fragmentos de string sem nenhum problema!
Eu tenho a preferência de montar a expressão regular como leio a string, sempre indo passo a passo da esquerda para a direita, dividindo ela em grupos. E usando constantemente alguma ferramenta para validar a RegEx antes de colocar no código.
Eu recomendo muito o RegEx101 para validar as expressões, pois é bem intuitivo e explica detalhadamente cada parte da expressão que deu match.
Uma RegEx aparece normalmente entre barras “/”, exemplos rápidos usando a tabela acima:
- Um número: /\d/
- Uma letra minúscula seguida de 3 números: /[a-z]\d{3}/
Após a última barra é comum aparecer alguns modificadores, por exemplo:
- Uma letra qualquer seguida de 3 números: /[a-z]\d{3}/i
- O “i” significa insensitive, ele não vai considerar o case, ou seja, a RegEx não verá diferença entre maiúsculas e minúsculas.
Alguns Modificadores
Segue uma colinha dos que eu uso com frequência:
Modificador |
Resultado |
i | Ignora o case da string |
g | Ocorrência global, por padrão é identificado apenas o primeiro match (exceto no PHP) |
m | Indica que uma string possui mais de uma linha |
s | Não dará matches para novas linhas |
No site RegEx101 tem uma relação completa de modificadores e metacaracteres que podemos usar! 🙂 Agora sim, HORA DA PRÁTICA! \o/
Exemplo clássico do CPF
Como validar se uma string está no formato de CPF, ou seja, 123.456.789-00?
Vamos dividir a string e ler ela da esquerda para a direita e analisar o que vamos precisar nela:
- Existem dígitos, logo vamos usar \d
- Existem pontos, mas para ele não representar qualquer caractere, precisamos escapá-lo
- Para escapar, usamos o \
- Existe um hífen normal
- E também quantificadores de repetição
Metacaracteres identificados: \d \ {n}. “Tá, mas… O hífen e o ponto não contam?”. Contam sim, mas eles serão representados como string na nossa RegEx e não como metacaracteres.
123 | . | 456. | . | 789 | – | 00 | |
RegEx |
\d{3} | \. | \d{3} | \. | \d{3} | – | \d{2} |
Resultado |
3 dígitos | ponto | 3 dígitos | ponto | 3 dígitos | hífen | 2 dígitos |
RegEx final: \d{3}\.\d{3}\.\d{3}-\d{2}
Um exemplo prático em JavaScript para validar um CPF:
const string = "123.456.789-00";
const matches = string.match(/\d{3}\.\d{3}\.\d{3}-\d{2}/);
if (matches) {
console.log("CPF válido");
} else {
console.log("CPF inválido");
}
Coletar o ID de uma URL
Agora é a vez tentar coletar o ID de uma URL referenciada para uma página de produtos e salvar o seu valor, um pouco diferente do exemplo anterior, agora precisamos extrair um valor e não validar o seu formato!
Vamos usar a URL:
https://exemploqualquer.com.br/categorias/produto/1234
Parece ser um exemplo mais complexo que o CPF, mas na verdade é mais simples. No CPF nós trabalhamos com muitos grupos, e aqui vamos ser bem mais diretos!
Quais metacaracteres identificamos para o uso?
- ID é um inteiro, logo \d
- Pode ter um dígito ou mais, então vamos usar o +
- E o resto? O resto é resto. 🙂
https:…/categorias/produto/ | 1234 | |
RegEx |
.*\/ | \d+ |
Resultado |
Pega QUAISQUER caracteres até a última ocorrência de uma /, atentar que escapamos ela para não ter o efeito de final da RegEx | Qualquer digito uma ou mais vezes |
Só isso? Quase… Vamos dividir em grupos para conseguir extrair o ID, então a RegEx final ficará: (.*\/)(\d+)
E para pegar APENAS o ID, vamos dar um replace de todo o conteúdo apenas pelo segundos grupo:
const url = "https://exemploqualquer.com.br/categorias/produto/1234";
const id = string.replace(/(.*\/)(\d+)/, "$2");
Ao substituir no replace pelo $2, indicamos o segundo grupo, poderia ser $1, $2,… $n. Depende de quantos grupos estão na RegEx. Ou seja, ali substituímos tudo que a RegEx deu match pelo segundo grupo, no nosso caso, o ID.
Coletar o ID de uma URL com Query String
E se a URL for essa:
https://exemploqualquer.com.br?produto=1234&categoria=2
Complicado, né? O produto pode estar antes ou depois da categoria, pode ter mais parâmetros, é uma infinidade de problemas que podemos encarar aqui. O que fazer?
Simples, ler da esquerda para a direita dividindo em grupos tudo fica mais fácil!
https:…com.br?produto= | 1234 | &categoria=2 | |
RegEx |
.*produto= | \d+ | .* |
Resultado |
Vamos coletar TUDO até o produto= | Qualquer dígito uma ou mais vezes | O resto? O resto é resto 🙂 |
Com isso garantimos que coletamos TUDO que aparece antes do parâmetro desejado no primeiro grupo, e inclusive o produto=, indiferente da ordem na query string e pegamos os dígitos após ele. E se algo aparecer depois? Tudo bem, cairá no nosso grupo 3.
Nossa RegEx final ficará assim: (.*produto=)(\d+)(.*)
Nosso exemplo em JavaScript:
const url = "https://exemploqualquer.com.br/categorias/produto/1234";
const id = string.replace(/(.*\/)(\d+)/, "$2");
Agora, caso não exista muito padrão no case do parâmetro esperado, como: produto, Produto, PRODUTO, PrODuTo, etc, nós podemos resolver de maneira rápida usando os modificadores. Basta colocar um “i” após a última barra da RegEx e tudo voltará a funcionar normalmente:
const url = "https://exemploqualquer.com.br/categorias/produto/1234";
const id = string.replace(/(.*\/)(\d+)/, "$2");
O que concluímos sobre expressões regulares?
As Expressões Regulares assustam de primeira vista, mesmo que neste post tenhamos usado apenas exemplos simples e básicos, se dividirmos em partes menores tudo fica mais fácil! Podemos fazer, inclusive, validações mais complexas como IP, E-mail, etc., pode ser trabalhoso, mas não será algo difícil.
RegEx dão grandes poderes, mas sabemos o que vem com poderes assim. Expressões regulares elevam o custo computacional, então use com moderação! 🙂
Acompanhe mais posts aqui no blog da Taller na categoria de Desenvolvimento de Software!