Expressões Regulares – Parte I

INTRODUÇÃO

Sabe quando nos deparamos com o problema de encontrar informações específicas em um grande texto? É… É nessa hora que sentimos a necessidade de entender as expressões regulares, aquela linha de código com um formato maluco cheio de símbolos que são difíceis de compreender. Mas calma, assim que conseguirmos decifrar os símbolos e seus significados, perceberemos que elas não são tão complicadas quanto parecem à primeira vista.

O objetivo desta série de posts é mostrar um jeito fácil de entender as expressões regulares para que possamos trabalhar mais facilmente com elas e perceber o quanto elas podem facilitar o nosso trabalho.

O QUE É EXPRESSÃO REGULAR (REGEX)?

Expressão Regular é uma representação formada por símbolos para encontrar padrões em strings. Serve para filtrar padrões de informações em qualquer tipo de texto, desde o valor de um campo de formulário ou simplesmente um search no seu editor de código predileto.

Resumindo, é uma linguagem de busca de padrões, onde dizemos o padrão (pattern) do texto que queremos encontrar, passamos o texto alvo (target) e pedimos para uma Regex Engine (motor) fazer essa busca, é esse motor que tem a função de avaliar o contexto e de fazer a busca.

Cada linguagem de programação tem o seu motor e apesar da Regex ter um padrão fixo, há algumas diferenças e detalhes na implementação em cada uma das linguagens. O que vai mudar de fato é a forma com que se trabalha, e não a lógica e os padrões em si das expressões regulares.

Para facilitar vamos usar o site https://regex101.com/, que possui diferentes Regex Engine (JavaScript, PHP, Python) e até gera o código para a linguagem dado o target e o pattern.

COMEÇANDO COM UM EXEMPLO BÁSICO

Vamos começar com um exemplo simples e aos poucos vou ensinando o que significa cada coisa. Vamos usar como exemplo um arquivo CSV com algumas informações de pessoas, contendo na sequência: Nome; CPF; Endereço; CEP; Telefone.

Imaginando que gostaríamos de extrair desse arquivo todos os CPFs, como faríamos isso?

Opa, usando uma Regex bem simples: \d\d\d\.\d\d\d\.\d\d\d-\d\d

Estranho, não é? Difícil de entender sem explicação, só olhando esses códigos malucos? A melhor forma de entender uma Regex é analisá-la por partes.

O \d é uma classe de caractere que vale qualquer número de zero a nove, também pode ser representada por [0-9].

O \. significa simplesmente um ponto, temos que colocar antes do ponto a barra invertida (\) para que a Regex Engine entenda o ponto com seu formato literal, se colocarmos somente o ponto sem a barra invertida, a Regex Engine entende de uma outra forma.

O (hífen) pode ser colocado na Regex direto, sem a barra invertida, que será entendido com o seu formato literal. Mas por que o hífen a Regex Engine entende e o ponto não? Simples, porque o ponto é um Metacharacter. What??? Calma, veremos o que isso significa ainda neste post.

Resumindo, o CPF é composto por pacotes de 3 números (\d\d\d ou [0-9][0-9][0-9]), pontos (\.) e um hífen (). Logo, temos:

Porém, percebam que no exemplo acima, o CPF do Marcio Silva não possui pontos e hífen, e com a Regex que criamos, não conseguimos capturar essa informação. Como podemos alterar a nossa Regex para conseguir capturar os dois tipos de CPF?

Para que os pontos e hífen não sejam obrigatórios, isso é, eles podem ou não aparecer no texto pesquisado, vamos utilizar um quantifier. Mas o que é quantifier? Vamos com calma, num próximo post veremos com mais detalhes o que isso significa, por enquanto vamos apenas utilizar um dos quantifiers para seguir com o nosso exemplo.

E, para esse caso, vamos utilizar o ponto de interrogação (?). O ponto de interrogação tem alguns significados diferentes nas expressões regulares dependendo de que maneira ele é utilizado. Um dos significados dele é o quantifier, que representa um atalho para dizer que aquele elemento pode ou não aparecer no texto pesquisado, tornando assim, o elemento opcional.

Logo, para considerar os dois casos de CPF, quando o ponto ou hífen aparecem e quando eles não aparecem no nosso alvo, precisamos alterar a nossa Regex para: \d\d\d\.?\d\d\d\.?\d\d\d-?\d\d

Perceba que agora ambos os casos foram capturados.

Esse é apenas um exemplo bem rústico e simples do uso de expressões regulares. Elas podem ficar muito mais elegantes e fáceis de ler e também muito mais complexas.

Vamos aproveitar esse mesmo exemplo e melhorá-lo um pouquinho. Estamos repetindo \d três vezes porque estamos procurando três dígitos. Imagina se o nosso alvo fosse alguma sequência com 10 números, teríamos que repetir \d 10 vezes? Poderíamos, e a Regex estaria correta, mas podemos também escrever de um jeito mais simples.

Para isso podemos aproveitar e conhecer mais um tipo de quantifier. O {n} significa que queremos que um determinado elemento apareça especificamente “n” vezes, onde “n” sempre é um número inteiro. Portanto, podemos escrever os \d\d\d de uma forma mais simples com: \d{3}.

Com esse novo quantifier, a nossa Regex fica mais simplificada e funciona igual a mostrada anteriormente.

METACHARACTER

Como vimos no exemplo anterior, o ponto é um metacharacter, mas o que isso significa? Metacharacter ou meta-caractere é todo caractere que não possui o seu valor semântico (literal) propriamente dito, ou seja, ele não tem o seu significado normal e sim um significado especial para a Regex Engine.

Em uma expressão regular, um ponto (.) sozinho tem o valor de qualquer caractere, isso significa que quando usamos o ponto na Regex, queremos capturar qualquer caractere que esteja no alvo.

Para conseguir “pegar” o ponto no nosso alvo, precisamos “escapar” do significado do metacharater e utilizamos a barra invertida (\) para isso. Assim “pegamos” o ponto com o seu significado semântico.

Há mais alguns caracteres que possuem esse mesmo comportamento, a maior parte deles são os quantifiers, como já comentei, veremos todos os quantifiers num próximo post.

CONCLUSÃO

Neste post vimos um pouquinho do que são as expressões regulares e como elas têm diversas formas de serem escritas, cada uma com seus símbolos diferentes. Nos próximos posts veremos mais coisas novas e faremos mais exemplos para ficar mais fácil de compreender cada detalhe.

Espero que esse primeiro post já tenha ajudado a tirar o medo de trabalhar com essas expressões malucas! Com certeza depois de terminar de ler todos os posts da série, vão entender muito mais de como trabalhar com elas.