0

A magia da Regex

#JavaScript
Gabriel Santos
Gabriel Santos

Você já ouviu falar em Regex?


Não é uma religião (mas poderia ser), nem uma linguagem de programação, e muito menos um bicho de sete cabeças.


Uma regex (regular expression) é um padrão que permite a identificação de caracteres em strings. Seguindo as formalidades para a criação de regex, é possível facilmente identificar caracteres e encadeamentos específicos dentro de strings e substituí-los como bem entender.


Claras vantagens


Mas por que escolher a regex dentre todas as outras opções possíveis para realizar essas tarefas? Porque ela simplesmente vai direto ao ponto. Enquanto a validação de um campo de formulário por meio de condicionais pode ser extremamente verbosa e de difícil leitura, a mesma validação feita por meio de uma regex pode ocupar apenas uma linha e ser muito mais precisa.


Nem tudo é um mar de rosas


Todo poder tem um preço, e, no caso das expressões regulares, esse preço é ter que lidar com sua aparência críptica (atenção ao p). Não são formalidades extremamente difíceis de serem entendidas, porém, aos olhos de um iniciante, podem parecer mais confusas que hieróglifos. Acredite, é plenamente compreensível que o medo tome conta de seu ser na presença de algo como isso:


/^\w+@[a-z]+(\.[a-z]{2,8})?\.[a-z]{2,8}$/i


O QUE DIABOS É ISSO? Essa é uma expressão regular para a validação de e-mails. Essa validação pode ser escrita de várias formas em regex, mas essa é suficiente por enquanto.


Calma, é mais difícil começar do que continuar, e todas as possibilidades que expressões regulares trazem definitivamente fazem valer a pena o empenho necessário para entender suas regras.


O básico necessário


Entender os símbolos básicos que compõem as expressões regulares faz tudo ficar mais claro. Então comecemos:


/

A barra para a direita (/) ou forward slash é o delimitador das expressões regulares. Resumindo, elas são como as aspas para as strings, e devem aparecer ao início e ao final da expressão.


/Waldo/


A regex acima será associada ao primeiro "Waldo" em uma string, caso ele exista nela.


//g

Caso o objetivo seja encontrar todos os casos da palavra dentro da string, basta usar a flag global (/g)


/Waldo/g


Essa regex será associada a todos os "Waldo" existentes na string em que se faz a busca.


//i


A flag /i serve para tornar a busca case insensitive, ou seja, não será feita distinção entre letras maiúsculas e minúsculas


/Waldo/gi


Essa expressão encontraria todos os "Waldo", mesmo que fossem "WaLDo" ou mesmo "WALDO".


[ ]


Os colchetes permitem a escolha de caracteres alternativos


/[W,B,N]aldo/g


Essa expressão associa 3 alternativas ao primeiro caractere da string. Logo, essa regex poderia ser associada a "Waldo", "Baldo" ou "Naldo".


[^]


Colchetes com o acento circunflexo representam a exclusão alternativa, buscando todas as ocorrências que NÃO envolvem os caracteres dentro dos colchetes na posição especificada.


/[^W]aldo/g


Essa expressão buscaria todas as ocorrências iniciadas por qualquer letra maiúscula do alfabeto, exceto "W". Logo, ela procuraria "Caldo", "Faudo", "Zaldo", mas não procuraria "Waldo"



Range [ - ]


O range ajuda a evitar repetição. Imagine que você quer procurar qualquer uma das letras do alfabeto no primeiro caractere de "_aldo".


Convenhamos que [a,b,c,d,e,f,g,h,i,j...] não parece uma alternativa viável. E não é mesmo. Fazendo o uso de ranges, essa tarefa se torna muito mais fácil:


/[A-Z]aldo/g


Você pode usar letras maiúsculas ou minúsculas e números no range, podendo ser [a-z], [A-Z] ou [0-9]. Você também pode juntar tudo em um só [a-zA-Z0-9].


Repeat [ ]{}


Apesar de o range resolver parte da questão da repetição, ele não resolve uma coisa: a própria repetição de ranges. Digamos que eu queira buscar uma palavra qualquer que tenha 5 letras minúsculas.


/[a-z][a-z][a-z][a-z][a-z]/


Essa é uma maneira possível de delimitar essa essa busca, mas não é a melhor. O repeat pode ser usado para evitar toda essa repetição de ranges. Vale destacar que ele também pode ser usado com letras normais, sem a necessidade dos colchetes.


/[a-z]{5}/


Eis o repeat, muito mais rápido e limpo. Um repeat também pode determinar um range de valores, podendo ir de um número a outro ou a infinito.


/[a-z]{2, 5}/


Busca a primeira palavra que tiver entre 2 e 5 letras (incluindo 2 e 5)


/[a-z]{5,}/


Busca a primeira palavra que tiver 5 ou mais letras


Metacaracteres


Metacaracteres são mais abreviações para facilitar a nossa vida. Digamos que você quer procurar qualquer dígito de 0 a 9. Você pode usar [0-9], mas isso pode ser encurtado ainda mais usando o \d, este que vai buscar apenas por dígitos de 0 a 9 nas posições especificadas.


Digamos que queremos buscar uma sequência de 7 números de 0 a 9. Podemos usar:


/\d{7}/


Alguns dos outros metacaracteres são:


\w -> busca letras maiúsculas, minúsculas, números e underlines


\s -> busca espaços em branco e tabs


\t -> busca apenas tabs


Caracteres especiais


+ -> quantificador de um ou mais. Colocado à frente de um caractere ou grupo para especificar que pode existir um ou mais dele, sendo esse mais um número indefinido.


/KAMEHAMEH(A)+/


Essa expressão vai encontrar a palavra "KAMEHAMEHAAA..." com uma quantidade indefinida de A ao final, podendo existir apenas um ou infinitos.


\ (backslash) -> É o clássico caractere de escape. É usado para literalizar caracteres especiais na expressão.


[ ] -> Conjunto (visto lá em cima)


[^ ] -> Negação alternativa


? -> quantificador zero-um: o caractere ou grupo que vier antes dele vai ser opcional, ou seja, pode existir ou não. A busca é indiferente a ele.


/Joana, (Carlos,)?Felipe/


Carlos é opcional para a expressão. Tanto a string "Joana, Carlos, Felipe" quanto "Joana, Felipe" dariam match.


. -> Sim, isso é um ponto final. Ele busca qualquer caractere existente naquela posição, exceto o caractere de quebra de linha.


* -> Quantificador zero ou mais: é quase como o quantificador do sinal de adição. A diferença é que o caractere ou grupo que ele marca será opcional na busca, ou seja, pode aparecer ou não.


Limitadores


São caracteres que especificam se a expressão buscada deve estar no fim da string, no começo ou ser a única da string (fim e começo)


^ -> O acento circunflexo fora dos colchetes especifica que a expressão buscada deve ser a primeira da string.


$ -> O cifrão especifica que a expressão deve ser a última da string.


Exemplificando, digamos que buscamos a seguinte palavra:


/Penguin/


Sem os limitadores, essa palavra pode ser encontrada em qualquer lugar da string, então um resultado possível seria:


"aaaaaaaaaaaaaaPenguinaaaaaa"


Essa string daria match, pois não foram especificados limitadores. Agora usando o limitador de início:


/^Penguin/


"aaaaaaaaaaaaaaPenguinaaaaaa" -> NÃO DARIA MATCH


"Penguinaaaaaaaaaaaaaaaa" -> DARIA MATCH


O mesmo vale para o limitador de final ($)


/Penguin$/


"aaaaaaaaaaaaaaaaPenguin" -> DARIA MATCH


Por fim, caso seu objetivo seja que a string seja EXATAMENTE a parte que você especificou na expressão, SEM MAIS NEM MENOS, use ^ e $ juntos.


/^Penguin$/


Apenas "Penguin" daria match


A cereja do bolo


Se passou por tudo isso com atenção, talvez já tenha percebido que você já é plenamente capaz de entender o verificador de e-mail trazido lá em cima.Tente entendê-lo:


/^\w+@[a-z]+(\.[a-z]{2,8})?\.[a-z]{2,8}$/i


As cores não têm significado especial. Servem apenas para delimitar cada parte da expressão.


Fragmentando a expressão, temos:


Limitador ^


\w+ que aceita letras, números e underlines sem uma quantidade definida (+)


@ nada de especial aqui, apenas um arroba de normal de e-mail


[a-z]+ essa é a parte do email que vem depois do arroba, aceitando apenas letras, e, nesse caso, em quantidade indefinida (+)


(\.[a-z]{2,8})? -> \. é o caractere de escape para usar o ponto literal, já que ele é um caractere especial. Essa parte vem depois do identificador do email, e aceita letras, sendo de 2 a 8. Perceba que esse pedaço é opcional (?).


Exemplificando: um e-mail pode terminar com .com, .com.br, .gov.br, etc. Percebe-se que ele pode ter duas partes separadas por dois pontos ou apenas uma (.com) com um ponto. Por isso, a primeira é opcional, e a próxima é obrigatória.


\.[a-z]{2,8} -> Também vem depois do identificador do email (ex: @gmail...), mas essa parte é obrigatória, pois todo e-mail tem pelo menos um ponto algumacoisa depois do identificador (@hotmail.com)


$ -> Limitador de final. Junto do limitador de início, especifica que somente a string que contém apenas o e-mail dará match. Nada mais, nada menos.


\i -> Flag que torna a busca case insensitive


Com isso chegamos ao fim desse artigo. Regex tem várias especificidades que não foram abordadas neste artigo, mas o conteúdo com certeza serve como uma boa base.


Tratei apenas das expressões em si, sem falar de seu uso com funções, pois cada linguagem de programação tem suas especificidades quando se trata de Regex.


Caso tenham sugestões de alteração ou encontrem erros, sintam-se à vontade para me notificar pelas respostas.


Como recomendação para a prática do que foi ensinado aqui, deixo o site https://regex101.com/, ótimo tanto para treinamento quanto para debug de expressões regulares!


Espero que esse artigo seja de alguma ajuda para você que se interessou :)

0
19

Comentários (0)

Entusiasta migrando para a área de tecnologia :)

Brasil