As expressões regulares, também chamadas de regex, são uma forma de especificar um padrão que corresponda a um texto que pretendemos encontrar, seja na saída de um comando ou dentro de um arquivo, e não são poucas as situações em que precisamos fazer esse tipo de busca. Este pequeno guia é um apanhado das técnicas e conceitos básicos de regex que eu aprendi ao longo dos últimos 15 anos lendo os dois grandes mestres no assunto: Aurelio Jargas e Julio Neves.
Ao contrário do que se pensa, não é apenas na programação que precisamos recorrer às expressões regulares. A maioria dos editores de texto e suítes de escritório oferecem alguma forma de busca utilizando expressões regulares, simplesmente por se tratar de uma forma muito eficiente para encontrar trechos do texto quando não sabemos qual é o seu teor exato, mas sabemos algum detalhe sobre ele que pode ser caracterizado como um padrão.
Por exemplo, dentro de um texto que contenha várias indicações de horários, os valores podem variar, mas eles sempre vão seguir o padrão HH:MM
, onde "H" e "M" sempre serão algarismos entre "0" e "9".
Sabendo disso, nós podemos "casar" (encontrar correspondência ou match) qualquer horário do exemplo com o padrão...
[0-9][0-9]:[0-9][0-9]
Se o horário que procuramos estiver no início de alguma linha, nós podemos ser ainda mais específicos...
^[0-9][0-9]:[0-9][0-9]
Os símbolos []
e ^
são o que chamamos de metacaracteres e eles é que irão compor a sintaxe das expressões regulares.
No caso, os colchetes representam uma lista dos caracteres válidos na nossa busca, e cada par corresponde a um caractere. O circunflexo, por sua vez, representa o início da linha.
Portanto, o padrão dessa regex pode ser "traduzido" da seguinte forma: começando no início da linha, eu quero dois caracteres de "0" a "9" seguidos de dois pontos (:
) e mais dois caracteres de "0" a "9".
Esse seria o nosso padrão de busca, e tudo que correspondesse a ele seria retornado pelo nosso editor de textos ou pelo comando que estivermos executando no terminal ou dentro do nosso programa.
As classes de metacaracteres
O nome é complicado, mas a ideia é simples. A fim de compor um padrão, as expressões regulares utilizam símbolos gráficos com significados bem definidos, chamados de "marcadores" ou "metacaracteres".
Dentro da sintaxe básica padrão, os metacaracteres são classificados em quatro grupos de acordo com a sua função na construção de um padrão:
* Representantes : representam caracteres
* Quantificadores: designam a quantidade de vezes
que representantes se repetem
* Âncoras : sinalizam o início e/ou o fim
de linhas e bordas
* Outros : são marcadores sem funções relacionadas
entre si, o que impede que sejam agrupados
em uma classe específica (portanto, "outros").
Embora existam mais metacaracteres do que veremos abaixo, com esse conjunto de 14 símbolos nós poderíamos representar praticamente qualquer padrão na forma de uma expressão regular.
Observação: devido ao seu excelente valor didático, nas descrições a seguir, eu vou utilizar os "apelidos" que tanto o Prof. Julio Neves quanto o autor Aurelio Jargas dão para os metacaracteres.
1. Representantes
META MENMÔNICO FUNÇÃO
-----------------------------------------------------------
. ponto casa com qualquer caractere
[...] lista lista de caracteres permitidos
[^...] lista negada lista de caracteres proibidos
1.1 Ponto: o necessitado - .
Casa com qualquer caractere, não importa qual seja, inclusive com o caractere ponto.
EXEMPLO CASA COM...
-----------------------------------------------------------
caj. cajá caju caja caj. caj, caj8 ...
.osa rosa Rosa tosa ...
con.erto concerto conserto con erto ...
1.2 Lista: a exigente - [...]
Casa apenas com um dos caracteres que estiverem listados entre os colchetes.
EXEMPLO CASA COM...
-----------------------------------------------------------
caj[uá] cajá caju
[Rr]osa Rosa rosa
con[cs]erto concerto conserto
Importante: tudo dentro da lista torna-se literal, exceto o traço (
-
) e a barra invertida (\
)!
EXEMPLO CASA COM...
-----------------------------------------------------------
35[,.]00 35,00 35.00
Outros exemplos de listas:
[0-9] algarismos de "0" a "9"
[A-Z] letras maiúsculas não acentuadas de "A" até "Z"
[a-z] letras minúsculas não acentuadas de "a" até "z"
[A-Za-z] letras maiúsculas e minúsculas não acentuadas
Além disso, as listas podem receber as chamadas classes POSIX, que são grupos de caracteres pré-definidos que só podem ser usados dentro de listas:
[:upper:] [A-Z] letras maiúsculas
[:lower:] [a-z] letras minúsculas
[:alpha:] [A-Za-z] maiúsculas/minúsculas
[:alnum:] [A-Za-z0-9] letras e números
[:digit:] [0-9] números
[:xdigit:] [0-9A-Fa-f] números hexadecimais
[:punct:] [.,!?:...] sinais de pontuação
[:blank:] [ \t] espaço e TAB
[:space:] [ \t\n\r\f\v] caracteres brancos
[:cntrl:] - caracteres de controle
[:graph:] [^ \t\n\r\f\v] caracteres imprimíveis
[:print:] [^\t\n\r\f\v] imprimíveis e o espaço
Uma das características mais importantes das classes POSIX, é que elas respeitam a definição do idioma do seu sistema (varável de ambiente
$LANG
) e, com isso, os caracteres acentuados são levados em consideração.
1.3 Lista negada: a experiente - [^...]
Seu comportamento é idêntico ao da lista, exceto pelo fato de que ela representa o que não pode ser casado no padrão, ou seja, ela casa com qualquer coisa que não esteja listada.
EXEMPLO CASA COM...
-----------------------------------------------------------
caj[^á] caju caj9 cajj ...
[^r]osa Rosa tosa cosa ...
con[^s]erto concerto conxerto con erto ...
Apesar das listas negadas poderem casar com qualquer coisa que não esteja listada, elas precisam casar com alguma coisa. Elas não casariam, por exemplo, com linhas vazias.
2. Quantificadores
META MENMÔNICO FUNÇÃO
-----------------------------------------------------------
? opcional zero ou um
* asterisco zero, um ou mais
+ mais um ou mais
{x,n} chaves quantidade de x até n
Antes de falarmos dos quantificadores em si, é importante ter em mente que todos eles sempre tentarão englobar o maior casamento possível de correspondências. O capítulo sobre quantificadores gulosos do site do Aurelio Jargas dá uma ótima explicação sobre como isso acontece.
2.1 Opcional: o opcional - ?
Indica que o caractere anterior pode ou não existir.
EXEMPLO CASA COM...
-----------------------------------------------------------
[ms]?ente mente sente ente
curti[ur!]? curtiu curtir curti! curti
esper?to esperto espeto
todas? todas toda
r?onda ronda onda
Uma outra característica do opcional, é que ele pode limitar o comportamento guloso dos quantificadores, inclusive o dele mesmo:
?? opcional não-guloso
*? asterisco não-guloso
+? mais não-guloso
{x,n}? chaves não-gulosas
2.2 Asterisco: o tudo ou nada - *
Indica que o caractere anterior pode aparecer em qualquer quantidade, inclusive não aparecer.
EXEMPLO CASA COM...
-----------------------------------------------------------
cas*a casa cassa cassssa caa ...
car*o caro carro carrrro cao ...
cant*o canto cano canttto ...
gal[oa]* galo gala gal galoooo ...
.*e[sx]*ta cesta sesta sexta esta exta eta reta ...
2.3 Mais: o pelo menos um - +
O comportamento é idêntico ao do asterisco, exceto pelo fato de que tem que existir pelo menos uma ocorrência do caractere anterior.
EXEMPLO CASA COM...
-----------------------------------------------------------
cas+a casa cassa cassssa ...
car+o caro carro carrrro ...
cant+o canto canttto ...
gal[oa]+ galo gala galoooo galaaa ...
.+e[sx]+ta cesta sexta ssexxxta resta testa ...
2.4 Chaves: o controle - {x,n}
Através das chaves, nós podemos especificar a quantidade mínima (x) e máxima (n) de ocorrências do caractere anterior, por exemplo:
{0,1} zero ou um (como o opcional)
{0,} zero ou mais (como o asterisco)
{1,} um ou mais (como o mais)
{5} exatamente 5 ocorrências
{3,} pelo menos 3 ocorrências
{2,8} de 2 a 8 ocorrências
{0,4} de nenhuma a 4 ocorrências
Não se usa {1}, já que é a mesma coisa que não especificar quantidade nenhuma para o caractere anterior.
3. Âncoras
META MENMÔNICO FUNÇÃO
-----------------------------------------------------------
^ circunflexo início da linha
$ cifrão fim da linha
\b borda borda
3.1 Circunflexo: o início - ^
O circunflexo marca o começo de uma linha.
Atenção! Não confundir com o circunflexo dentro das lista negadas!
^[0-9] - representa uma linha que começa
com um caractere numérico.
^[^0-9] - representa uma linha que NÃO começa
com um caractere numérico.
O circunflexo só é especial no começo da regex ou compondo a lista negada. Fora isso, ele é visto como um caractere literal.
[0-9]^ - representa um dígito seguido
de um circunflexo literal.
^^ - representa uma linha que começa
com um circunflexo literal.
3.2 Cifrão: o fim - $
O cifrão marca o final de uma linha de texto e, tal como o circunflexo no lado oposto, ele só tem um significado especial quando está no final da regex. Exemplos:
^$ - representa uma linha vazia.
^.{20}$ - representa uma linha com 20 caracteres.
,[0-9]{2}$ - representa uma linha que termina
com uma vírgula e dois dígitos numéricos.
[^;]$ - representa linhas que NÃO terminam
com ponto e vírgula.
3.3 Borda: a limítrofe - \b
A borda é uma âncora que serve para marcar os limites de uma palavra, ou seja, o seu começo e/ou o seu fim. É importante notar que o conceito de "palavra" em expressões regulares é restrito a trechos contínuos que contenham apenas letras, números e o sublinhado (_
).
EXEMPLO CASA COM...
-----------------------------------------------------------
bem bem bem-vindo sabemos bebem
\bbem bem bem-vindo
bem\b bem bem-vindo bebem
\bbem\b bem bem-vindo
Apesar de não estar listada no grupo padrão de âncoras, existe ainda um marcador que representa a negação da borda, o \B
.
Ainda com os exemplos acima, o \B
seria a solução para casar a palavra "sabemos", onde o padrão "bem" não aparece nas bordas da palavra, ou seja:
EXEMPLO CASA COM...
-----------------------------------------------------------
bem bem bem-vindo sabemos bebem
\Bbem sabemos bebem
bem\B sabemos
\Bbem\B sabemos
4. Outros
META MENMÔNICO FUNÇÃO
-----------------------------------------------------------
\ escape torna literal o caractere seguinte
| ou um ou outro
(...) grupo delimita um grupo
\1...9 retrovisor texto casado no grupo n
4.1 Escape: a kriptonita - \
A "contrabarra", ou "barra invertida", remove os significados especiais dos metacaracteres, tornando-os literais dentro da regex. A este processo, nós damos o nome de "escapar".
A contrabarra escapa inclusive a si mesma:
\\
equivale a uma\
literal
Quando seguida de um número de "1" a "9", a contrabarra estará delimitando outro metacaractere, o "retrovisor", como veremos mais para frente. Além disso, existem alguns caracteres especiais que podem surgir numa regex após uma contrabarra, como é o caso do \n
, que representa uma quebra de linha, ou do \t
, que representa uma tabulação.
4.2 Ou: um ou outro - |
O "ou", representado por uma barra vertical, permite que o casamento ocorra com qualquer valor antes e depois dele.
Exemplo: mandioca|aipim|macaxeira
Numa busca, qualquer uma das três palavras seria casada.
Na prática, uma lista ([...]
) também se comporta como um tipo de "ou", e deve ser considerado quando o que muda nas alternativas são apenas alguns caracteres.
Exemplo: ro[dst]a é o mesmo que roda|rosa|rota
Também podemos casar a ausência de texto através do "ou"...
Exemplo: bom( |-|)bocado casaria com:
bom bocado
bom-bocado
bombocado
4.3 Grupo: a patota - (...)
O grupo tem a função de agrupar (óbvio!) certos padrões dentro de uma regex com a finalidade de permitir que se faça referência a eles posteriormente.
Observação: é possível fazer agrupamentos dentro de agrupamentos, e o comportamento será idêntico ao dos parêntesis na matemática, ou seja, a prioridade será sempre do grupo mais interno para o mais externo.
Os metacaracteres quantificadores podem ter seus poderes ampliados pelo grupo (juntos somos mais fortes!), permitindo a correspondência quantificadas de expressões inteiras e não apenas de caracteres.
EXEMPLO CASA COM...
-----------------------------------------------------------
(bom)+ bom bombom bombombom ...
(per)?feito perfeito feito
O grupo também amplia o poder "ou" dando-lhe um contexto.
EXEMPLO CASA COM...
-----------------------------------------------------------
(in|con)certo incerto concerto
(pre|per|rare)?feito prefeito perfeito rarefeito
(mini|(su|hi)per)?mercado minimercado supermercado
hipermercado mercado
4.4 Retrovisor: o saudosista - \1...9
Uma outra características dos grupos, é que nós podemos fazer referências posteriores aos conteúdos casados dentro deles através dos retrovisores.
Grife-se bem que estamos falando dos conteúdos, não das expressões dentro dos grupos.
A numeração dos grupos começa sempre dos parêntesis mais externos ou à esquerda e vai até os mais internos ou mais à direita.
(...) ... (...)
^ ^
| |
\1 \2
(...(...)) ... (...)
^ ^ ^
| | |
\1 \2 \3
São permitidos apenas 9 retrovisores, e a expressão \10
, por exemplo, estaria se referindo ao conteúdo casado no grupo 1 seguido do algarismo "0".
Conclusão
O assunto expressões regulares está longe de ser esgotado, mas espero que este compilado sirva ao menos como uma referência rápida sobre os seus princípios básicos. É sempre bom lembrar que existem diversas outras implementações de regex, e elas podem diferir muito do padrão POSIX, que é o utilizado, em princípio, no shell do Linux. No mais, como sempre, fique à vontade para ampliar e corrigir qualquer informação equivocada que, eventualmente, você encontre aqui.
Você poderá encontrar informações muito mais completas visitando a minha principal fonte:
Aurelio Marinho Jargas
Expressões Regulares - Guia de Consulta Rápida
Ou assistindo a essa aula sensacional:
Prof. Julio Neves
Aula de Expressões Regulares no Youtube
 
Nenhum comentário:
Postar um comentário
O sistema de comentários do Blogspot é um lixo e praticamente me obriga a liberar ou moderar todos os comentários. Portanto, eu peço perdão antecipadamente caso o seu comentário demore para aparecer.
Mas não se acanhe por causa disso! :-)