Expressão regular — ou simplesmente REGEX para encurtar — é uma sequência de caracteres que define um padrão de busca, é geralmente utilizada dentro de algoritmos de pesquisa de texto para busca e/ou substituição de sequências/padrões de caracteres dentro de strings e Por sua praticidade, está implementada dentro de linguagens de programação, ferramentas e até mesmo alguns aplicativos.
Claro que isto aqui não tem o objetivo de ser um tratado sobre o assunto, servindo mais como uma introdução básica para que a visão de algo como um ^[A-Za-z]+ [0-9].*[A-Z][a-z]+$ deixe de causar traumático.
Nesta primeira parte dois conceitos importantes em REGEX, a quantificação (número de vezes que repete, ou não) e o grupo (lista de possíveis ocorrências). E para os exemplos resolvi usar um trauma pessoal, a grafia do meu nome, ou seja, aquilo que me faz recitar o mantra “com «i», dois «n» e «i» no final” sempre que preciso explicar a alguém como escrever meu nome. 🙂
Antes de começar
Então, a primeira coisa a fazer é criar o combinador responsável por produzir as 48 grafias possíveis e foneticamente equivalentes do meu nome na língua portuguesa.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
let CASE=0 | |
for A in 'Ge' 'Gi' 'Gy' 'J' ; do | |
for B in 'v' 'w' ; do | |
for C in 'n' 'nn'; do | |
for D in 'e' 'i' 'y' ; do | |
let CASE++ | |
printf "Caso %02d – %so%sa%s%s%s\n" $CASE $A $B $C $D | |
done | |
done | |
done | |
done |
Execute o programa, escolha um dos casos e o pronuncie um dos nomes impressos e perceba como soarão parecidos.
Mas, por enquanto, o que importa é verificar apenas uma das grafias, a correta:
$ ./names.sh | grep "Giovanni"
Caso 17 - Giovanni
Neste caso apenas uma ocorrência foi encontrada, o que está certo pois é justamente o que foi pedido para ser pesquisado numa comparação de strings feita caractere por caractere.
E agora começamos com o “jogo de achar Giovanni”.
Quantificação de caracteres
Como na língua portuguesa a repetição da letra «n» não tem função fonética e o resultado final é acabarem sendo tratadas como se uma única letra fossem uma das letras «n» pode ser omitida em alguns casos. Então como achar “Giovanni” e “Giovani” sem recorrer a algo do tipo?
if [[ ${NOME} == "Giovanni" || ${NOME} == "Giovani" ]]; then
...
fi
Uma das formas de tratar a repetição de um caractere (ou a sequência destes) em REGEX é indicando entre chaves — { e } — a quantidade de vezes em que se repetirá.
Especificamente neste caso a letra «n» deverá aparecer no mínimo uma vez e no máximo duas vezes (estou desconsiderando a hipótese da letra «n» se repetir três ou mais vezes).
$ ./names.sh | egrep "Giovan{1,2}i" Caso 14 - Giovani Caso 17 - Giovanni
Ah sim, duas coisas, as cores são apenas para ajudar a visualizar a parte da string afetada pelo REGEX, e o uso do egrep equivale a utilizar grep -E.
A sintaxe dos valores dentro das chaves pode ser a seguinte:
- n{2} — Duas ocorrências da letra «n»;
- n{,2} — Até duas ocorrências da letra «n» ou nenhuma e
- n{2,} — No mínimo duas repetições da letra «n», sem uma quantidade máxima definida.
Há outra forma de tratar quantidades, acrescentando o sinal de soma — + — após o caractere para indicar uma ou mais ocorrências do mesmo, funcionando como se fosse o “n{1,}” e, portanto, não servindo para este caso.
Um ou outro caractere
Outro erro comum é a troca da letra «i» pela letra «e» no começo, no final ou em ambos. Aqui é preciso verificar esta permuta ou mais precisamente a ocorrência destas duas alternativas com a criação de grupo contendo os caracteres que poderão aparecer naquela sequência de caracteres.
Para criar um grupo em REGEX basta listar as alternativas colocando-as entre parênteses — ( e ) — e utilizando a barra vertical — | — para separá-las.
Testando primeiro com um grupo no começo do nome:
$ ./names.sh | egrep "G(e|i)ovan{1,2}i" Caso 02 - Geovani Caso 05 - Geovanni Caso 14 - Giovani Caso 17 - Giovanni
Depois um grupo no final do nome:
$ ./names.sh | egrep "Giovan{1,2}(e|i)" Caso 13 - Giovane Caso 14 - Giovani Caso 16 - Giovanne Caso 17 - Giovanni
E finalmente com os dois grupos:
$ ./names.sh | egrep "G(e|i)ovan{1,2}(e|i)" Caso 01 - Geovane Caso 02 - Geovani Caso 04 - Geovanne Caso 05 - Geovanni Caso 13 - Giovane Caso 14 - Giovani Caso 16 - Giovanne Caso 17 - Giovanni
Lembrando que é possível usar mais de um caractere dentro do grupo e até grupos dentro de grupos.
Grupo dentro de grupo
E se ao invés da letra «G» for utilizada a letra «J»? Claro que aqui vou considerar a destruição do ditongo com as letras «e» e «i» deixando de existir e toda a sílaba virando «Jo».
$ ./names.sh | egrep "(J|G(e|i))ovan{1,2}(e|i)" Caso 01 - Geovane Caso 02 - Geovani Caso 04 - Geovanne Caso 05 - Geovanni Caso 13 - Giovane Caso 14 - Giovani Caso 16 - Giovanne Caso 17 - Giovanni Caso 37 - Jovane Caso 38 - Jovani Caso 40 - Jovanne Caso 41 - Jovanni
E agora apareceu o caso 38, justamente a grafia da foto! 🙂
Finalizando esta parte
Adicionando agora um pouco mais de entropia com as letras «w» e «y»! A primeira formando um novo grupo com a letra «v» e a outra sendo adicionada aos grupos “(e|i)”.
$ ./names.sh | egrep "(J|G(e|i|y))o(v|w)an{1,2}(e|i|y)" Caso 01 - Geovane Caso 02 - Geovani ... Caso 47 - Jowanni Caso 48 - Jowanny
Liberando assim todas as 48 grafias criadas pelo programa e terminando esta primeira parte. Para a próxima parte será a vez de trabalhar com um pouco de incerteza com a ajuda dos curingas.
Até!
Pingback: Expressões regulares, o básico – parte 2 | giovannireisnunes
Pingback: Expressões regulares, o básico – parte 3 | giovannireisnunes
Que maravilha essa série de artigos Giovanni! Explicou muito bem e escolheu exemplos que ilustram bem os conceitos. A formatação com cores também ajuda bastante a enxergar os casamentos. Nota 10!
CurtirCurtir
Obrigado!
CurtirCurtir