Ir para o conteúdo

E o regex? Como vai?

13 min. de leitura

Avatar de Antônio Marcos dos Santos da Rosa

Antônio Marcos dos Santos da Rosa Autor


Com o intuito de compreender o que acontecia naquele amontoado sem sentido de caracteres que meus colegas chamavam de regex, decidi estudar o assunto e, agora, gostaria de compartilhar o que descobri com vocês.
Espero que, ao final desse artigo, todos nós possamos entender um pouco mais desse tal de regex.

Mas o que é Regex?

Regex é a abreviação do inglês Regular Expressions, traduzido para o português como expressões regulares. Com regex você pode buscar, validar e alterar qualquer padrão de caracteres em qualquer texto.

Três pontos fortes em expressões regulares são:

Buscas:

Você consegue encontrar determinados padrões dentro de qualquer sequência de caracteres, por exemplo, a busca por e-mails dentro de um texto.

Validações:

Você pode fazer a validação dos mais variados padrões, como telefone, e-mail e senha.

Substituições:

Pode substituir qualquer trecho, palavra ou letra dentro de um texto.

A estrutura…

Lembram-se da imagem do começo da postagem? Vamos observá-la com mais atenção.

Se você nunca teve contato com regex, provavelmente isso não faz sentido algum, correto? Montaremos algumas receitas e, depois, voltaremos nessa para ver se nossa percepção mudou.

Receita?!

Isso! Expressões regulares também são chamadas de receitas. Mas antes de falar de receita, que tal conhecermos os ingredientes?

A estrutura de expressões que será apresentada nesse artigo é a da linguagem Javascript, em outras linguagens a estrutura pode sofrer algumas alterações!

Imagine que temos o seguinte texto:

Nossa primeira missão é:

Buscar todas as letras “E” do texto.

Vamos montar uma expressão regular para isso. Toda expressão regular começa com “/” e termina com “/ ”, então vamos fazer isso…

O que estiver entre essas duas barras vai determinar o que queremos encontrar, como nossa missão é achar as letras “E” dentro do texto, vamos por um “E” dentro de nossa expressão.

Agora com o auxílio do Vs Code e utilizando a linguagem Javascript, vamos rodar uma busca no texto com nossa expressão regular…

Utilizei o método String.prototype.match() que recebe uma expressão regular e retorna tudo que corresponde ao que foi determinado na expressão. No nosso caso, queremos as letras “E”, vamos ver o resultado…

Ué, veio um array com um único “E”, uma chave valor com o índice desse caractere, outra chamada input mostrando o texto de busca e uma groups com o valor indefinido… Nós estávamos esperando um array de letras “E”, e não foi isso que aconteceu devido a falta de flags

Flags:

Podemos entender flags como “comandos extras” para nossa expressão regular, abaixo seguem as flags e para o que cada uma serve:

g : Com essa flag, a expressão retorna todas as correspondências, não se limitando a primeira que achar;

i : Aplicando essa flag você está dizendo para expressão que pode ignorar maiúsculas e minúsculas;

m : Com essa flag, a expressão trata caracteres de início e fim (^ $) delimitando a cada nova linha, e não o texto por completo;

Essas são algumas flags, existem outras que variam de linguagem para linguagem.
Agora, vamos ver como fica nossa busca com a utilização das flags.

flag é aplicada após o fechamento da expressão, no nosso caso, colocamos a flag “g” para varrer todo o texto e não se limitar ao primeiro resultado, e a flag “i” que serve para não haver a diferenciação entre caracteres minúsculos e maiúsculos. Então, o resultado da nossa busca agora é…

Resultado:

Olha só, temos agora um array de letras “E”, mas está correto? Temos todos os nossos caracteres “E” aqui? Vamos conferir.

Nosso retorno teve um total de 8 letras “E”, mas no texto existem 10 letras “E”. Neste momento, podemos perceber um padrão, só não nos retornaram as letras com acento.

Para resolver isso vamos falar de um ingrediente muito importante da nossa receita:

Caracteres:

Temos dois tipos de caracteres no regex:

Caracteres Simples: São os caracteres padrões como A, b, C, 1, 3, ., o próprio “E” que utilizamos na nossa expressão é um caractere simples, Resumindo, é a escrita literal. Se quero buscar, validar ou substituir uma letra, número ou qualquer outra coisa “chumbada”, utilizo de caracteres simples, exemplos:

Roberto, 123, abc123, A, a, 2, é, ã, …

Beleza, então precisamos adicionar o “É” a nossa expressão para que retorne todas as letras “E” como queremos, vamos acrescentar isso na nossa expressão…

Agora vamos testar e ver o resultado…

Rodamos o código e o resultado que temos é:

Null? Mas por quê? A resposta é simples, estamos procurando por um padrão “eé” e em nenhum momento isso acontece em nosso texto, o que queremos, na verdade, são letras “E” ou letras “É”, e como fazemos isso?

Com meta caracteres…

Meta caracteres: São caracteres que executam alguma função dentro de uma expressão regular, eles não tem seu valor literal como caracteres simples, mas aplicam algum tipo de efeito na expressão. Agora, vamos utilizar um meta carácter na nossa expressão e ver o seu efeito, estou falando do…

| (pipe): Esse meta carácter representa o OU, quando colocado em uma expressão entre alguns caracteres ele indica que você quer o que está a esquerda dele OU o que está a direita.

Vamos ver isso na prática.

Testando novamente…

O resultado é?

Isso!!

Chegamos onde queríamos, mas é só o começo! Vamos dar uma olhada em outro meta carácter.

. (ponto): O ponto seria um coringa. Quando se tem um ponto em uma expressão regular, estamos dizendo que, naquela posição, aceitamos qualquer carácter… Vamos fazer um teste em nossa expressão colocando um “.” nela.

Rodando o código…

O resultado que temos é o seguinte:

Viram? Ele traz qualquer coisa, todos os caracteres e espaços do texto… Mas como todo meta carácter, podemos fazer com que ele se torne um carácter simples aplicando uma “\” antes dele… Vamos fazer isso e ver o que acontece:

Rodamos o código novamente:

E o resultado é:

Isso mesmo! Um ponto literal, que é o ponto que temos no final do texto:

Outros meta caracteres:

Representantes :

[ ] (conjuntos): Conjuntos são definidos por [ ], então sempre que quero usar um conjunto, eu aplico colchetes dentro da expressão e defino dentro deles os caracteres que eu quero que façam parte desse conjunto. Vamos testar uma busca por vogais utilizando um conjunto…

Agora vamos testar isso no nosso código…

E o resultado é…

Percebem que quando estamos colocando os caracteres dentro de um conjunto estamos fazendo o mesmo que escrever assim:

Conjuntos também podem ser usados com intervalos de caracteres, por exemplo, quando queremos todos os números de nosso texto:

Rodando o código…

O resultado é…

Perfeito! pegamos todos os números no intervalo de 0–9.

Alguns outros exemplos de conjuntos…

[a-z], [A-Z], [À-ú]

Esses intervalos estão na tabela UNICODE:

https://unicode-table.com/pt/#basic-latin

Mas, se eu quero que só não seja selecionado o que está dentro do conjunto, eu posso negá-lo.

Rodando o código…

Temos o resultado…

Percebam que ele trouxe até mesmo os espaços em branco, e não trouxe nenhum número.

Um detalhe importante dentro de conjuntos: a maioria dos meta caracteres tem valor literal sem a necessidade da “\” antes deles.

Lembram que precisávamos de um “\” para o ponto ser realmente considerado um ponto pela expressão? Vamos testar o que acontece quando ele está dentro de um conjunto.

Resultado:

Viu só,?! Ele é realmente considerado um ponto.

Quantificadores:

São meta caracteres que definem quantidade.

Para exemplificar cada um deles utilizaremos o seguinte grupo de caracteres:

Começaremos pelo quantificador “?”, que representa zero ou um
Vamos montar a seguinte expressão:

Rodaremos nosso código. O que esperamos é que retorne 1 ou 11 já que o segundo 1 da expressão é opcional…

O resultado:

Vamos entender esse resultado abaixo. Representamos a seleção feita com cores. Assim que ele encontra um “1”, ele verifica se o que vem após cumpre o requisito para ser adicionado ao retorno ou não.

Vamos fazer um exemplo com o um ou mais que é representado pelo “+”, acredito que, com esse próximo exemplo, o entendimento do quantificador anterior fique claro.
Nossa expressão fica assim:

Rodamos o código…

E o resultado deve conter “11”, ou sequências maiores do caractere “1”

Perfeito! Como agora tínhamos a necessidade de, pelo menos um caractere “1” presente após o primeiro “1”, não temos o retorno do “1” sozinho como acontece no exemplo anterior, e também como não temos um limite de caracteres, ele vai trazendo até que o próximo não corresponda ao que é solicitado, nesse caso, as vírgulas que param esse fluxo…

Mas faltou trazer o primeiro “1” junto nessa busca, e conseguimos fazer isso com o quantificador zero ou mais, que é representado pelo “*”. Montamos a expressão e veremos o que acontece.

Rodamos o código…

E o retorno é…

Exatamente como esperávamos.

E para finalizar os quantificadores temos o { }, com ele você consegue definir intervalos. Abaixo alguns exemplos:
{0,1}: Semelhante ao ?
{1,}: Semelhante ao +
{0,}: Semelhante ao * 
{2}: Aqui define um valor exato
{1,5}: Aqui um intervalo de 1 a 5

Vamos ver isso na prática com algumas buscas, iremos utilizar o seguinte texto:

Primeiro, vamos tentar com o {0, 1}, montando a seguinte expressão regular:

Rodando isso:

O resultado é:

Como esperado, ele teve um resultado semelhante a uma expressão com o quantificador “?”. Ele pega o último caractere informado e o torna opcional…

Da mesma forma se usarmos a seguinte expressão:

O resultado se assemelha ao do quantificador “ + ”:

Resultado:

Ao usar uma expressão como essa…

Temos um resultado igual ao da utilização do quantificador “ * ”.

Resultado:

Agora chegamos a um cenário que é só desse quantificador, uma quantia exata.

Rodando essa expressão, temos um resultado exato na quantia de caracteres retornados.

Resultado:

Outro cenário particular desse quantificador são intervalos específicos, como…

Aqui você define um mínimo e um máximo de caracteres que devem conter na sua busca. No caso do nosso exemplo, teremos um retorno com 5 letras “R”.

Resultado:

Grupos:

Também temos os grupos, que são definidos por ( ) parênteses. Quando você define um grupo, consegue buscar o mesmo grupo mais de uma vez… Vamos exemplificar….

Se fossemos selecionar sequências como o “hehehehe” na frase acima, teríamos que definir ele na nossa expressão da seguinte forma:

Mas se a sequência de risos aumenta ou diminui? Teríamos um problema no nosso retorno, porém com grupos podemos superar isso da seguinte forma…

Primeiro, definimos um grupo de caracteres que queremos buscar, nesse caso o “he”.

Em seguida, definimos que queremos esse grupo por indefinidas vezes colocando um quantificador “+” para dizermos a expressão que queremos uma ou mais repetição desse grupo:

E se rodarmos nosso código:

O resultado:

Vamos a mais um exemplo onde grupos facilitam as coisas, vejamos abaixo:

Acima temos duas referências a pessoas, uma com um pronome de tratamento abreviado Sr, e outra não, porém queremos que nossa expressão seja flexível nesse caso, então montamos ela utilizando grupos.

Nós definimos um grupo com Sr e \s

Mas o que é esse “ \s ” ????

Esse cara faz parte dos ShortHands….

São “atalhos” para determinados conjuntos de caracteres, vamos ver alguns exemplos:

\w : Seria o mesmo que [a-zA-Z0–9_]

\W : Seria a negação do \w , então, [^a-zA-Z0–9_]

\d : Representa o conjunto [0–9]

\D : É a negação do \d que seria [^ 0–9]

\s : Representa os espaços, tabulações, nova linha, etc…

\S : Por sua vez, é a negação de \s que seriam todos os caracteres não espaços.

Vamos exemplificar isso, imaginem que temos que encontrar as partes iniciais de qualquer e-mail até o @, exemplo:
meu-email@
No seguinte texto:

Sem os ShortHands, teríamos uma regex mais ou menos assim:

Essa expressão traria os dois inícios de e-mail, mas caso fosse alterado o texto para algo como:

Nossa expressão já não iria ser eficaz, e para conseguir atingir uma gama grande de possibilidades, nós teríamos que criar uma expressão regex enorme, ou simplesmente fazer o seguinte:

E assim, teremos uma grande variação nas possibilidades de retorno… Claro, isso não é bala de prata, mas já ajuda, e muito. Vamos rodar nosso código e ver o resultado:

Resultado:

Bordas:

Também temos meta caracteres usados para bordas de texto, vejamos quais são eles:

^ : Inicio de linha
$ : Fim de linha
\b: Borda

Para exemplificar esses meta caracteres usaremos o seguinte texto:

Vamos buscar por “Miguel” no texto e ver o que acontece:

Rodando uma busca com essa expressão:

O resultado:

Ele trouxe os dois resultados que contém nesse texto, mas e se quisermos somente o primeiro?
Podemos fazer da seguinte forma…

Se rodamos o código com a adição desse meta caractere, o resultado é outro:

O resultado:

Mas se quisermos o “Miguel ”do final da frase…

Rodando o código:

O resultado:

E para finalizar, vamos testar o \b que representa bordas. Temos o seguinte texto:

Se quisermos palavras que começam com “RO” podemos utilizar bordas para isso.

Rodando o código:

O Resultado:

Caso desejássemos palavras que terminassem com “RO”, faríamos da seguinte forma:

Rodando:

Resultado:

Existem outros meta caracteres, aconselho que pesquisem o assunto…


Bom pessoal, chegamos ao fim do artigo, espero que o que escrevi tenha ajudado um pouco no entendimento de vocês a respeito do tal regex, e antes de irem embora… esta expressão que estava no início do artigo, faz mais sentido agora?

Um abraço pessoal, sou muito grato a todos que deram seu tempo e atenção a leitura desse artigo, até o próximo!