1. Expressões Regulares

    Baseado no livro Guia de Expressões Regulares de Aurélio Marinho Jargas

  2. Definição

    • "Uma expressão regular é um método formal de se especificar um padrão de texto".
    • "É uma composição de símbolos, caracteres com funções especiais, que, agrupados entre si e com caracteres literais, formam uma seqüência, uma expressão. Essa expressão é interpretada como uma regra, que indicará sucesso se uma entrada de dados qualquer casar com essa regra, ou seja, obedecer exatamente a todas as suas condições".
  3. Ou ainda...

    • "uma maneira de procurar um texto que você não lembra exatamente como é, mas tem idéia das variações possíveis";
    • "uma maneira de procurar um trecho em posições específicas como no começo ou no fim de uma linha, ou palavra";
    • "uma maneira de um programador especificar padrões complexos que podem ser procurados e casados em uma cadeia de caracteres";
    • "uma construção que utiliza pequenas ferramentas, feita para obter determinada seqüência de caracteres de um texto".
  4. Um pouquinho de História

    • A fecundação dessas expressões aconteceu no ano de 1943, quando os "pais", dois neurologistas, publicaram um estudo que teorizava o funcionamento dos nossos neurônios.
    • Anos depois o "parteiro", um matemático, descreveu algebricamente os modelos desse estudo, utilizando símbolos para representar seus recém-criados grupos regulares (do inglês "regular sets"). Com a criação dessa notação simbólica, nasceram as expressões regulares, que durante toda a sua infância e juventude (cerca de 20 anos), foram bastante estudadas pelos matemáticos da época.
  5. E onde fica a computação

    • O encontro com o computador, só aconteceu mesmo em 1968, em um algoritmo de busca utilizado no editor de textos qed, que depois virou o ed, EDitor padrão dos primeiros sistemas Unix. Este ed tinha o comando de contexto g, que aceitava expressões regulares e um comando p, e sua sintaxe ficava g/RE/p ("Global Regular Expression Print"), que deu origem ao aplicativo grep, que por sua vez originou o egrep.
    • Finalmente em 1986 foi criado o divisor de águas, um pacote pioneiro em C chamado regex que tratava das expressões regulares e qualquer um poderia incluí-lo em seu próprio programa, de graça. Opa! Falaram as palavras mágicas: "de graça". Aí não teve mais volta, as expressões caíram no gosto popular e cada vez mais e mais programas e linguagens as utilizam.
  6. Os Metacaracteres

    Representantes - são metacaracteres cuja função é representar um ou mais caracteres.

     

    meta mnemônico função
    . ponto um caractere qualquer
    [...] lista lista de caracteres permitidos
    [^...] lista negada lista de caracteres proibidos
  7. Os Metacaracteres - Continuação

    Quantificadores - servem para indicar o número de repetições permitidas para a entidade imediatamente anterior.

     

    meta mnemônico função
    ? opcional zero ou um
    * asterisco zero, um ou mais
    + mais um ou mais
    {n,m} chaves de n até m
  8. Os Metacaracteres - Continuação

    Âncoras - eles não casam caracteres ou definem quantidades, ao invés disso eles marcam uma posição específica na linha.

     

    meta mnemônico função
    ^ circunflexo início da linha
    $ cifrão fim da linha
    \b borda início ou fim de palavra
  9. Os Metacaracteres - Continuação

    Outros - têm funções específicas e não relacionadas entre si, portanto não podem ser agrupados em outra classe fora a tradicional "outros".

     

    meta mnemônico função
    \c escape torna literal o caractere c
    | ou ou um ou outro
    (...) grupo delimita um grupo
    \1...\9 retrovisor texto casado nos grupos 1...9
  10. Exemplos Práticos 1

    Como procurar em um texto a palavra "não", mas quem digitou este texto às vezes o acentuou, outras não?

  11. Exemplos práticos 1 - Continuação

    • n.o - não, nao, neo, noo, anão, neofone, ...
    • n[ãa]o - não, nao, anão, ...
    • \bn[ãa]o\b - não e nao
    • Nesta expressão você encontra a palavra não escrita de qualquer forma:
    • \b[Nn][ÃãAa][Oo]\b - não, nao, Não, NÃO, NãO, ...
  12. Exemplos práticos 2

    Se em um texto, eu preciso encontrar todas as datas no formato dd/mm/yy para troca-las para o formato dd/mm/yyyy.

  13. Exemplos práticos 2 - Continuação

    • ../../..
    • [0-9][0-9]/[0-9][0-9]/[0-9][0-9]
    • [0-9]{2}/[0-9]{2}/[0-9]{2}
    • (0[1-9]|[12][0-9]|3[01])/(0[1-9]|[1][0-2])/([0-9]{2})
  14. Exemplos práticos 3

    Você precisa buscar todas as linhas de um texto que iniciam com "A", ou então, terminam com "?".

  15. Exemplos práticos 3 - Continuação

    • ^A
    • \?$
  16. Exemplos práticos 4

    Você precisa buscar linhas em branco no texto.

  17. Exemplos práticos 4 - Continuação

    • ^$
  18. Exemplos práticos 5

    Você precisa de linhas que tenham entre 20 e 60 caracteres.

  19. Exemplos práticos 5 - Continuação

    • ^.{20,60}$
  20. Exemplos práticos 6

    Você precisa encontrar o termo Licença, mas ele aparece tanto em inglês como em português.

  21. Exemplos práticos 6 - Continuação

    • Licen(ça|se)
  22. Exemplos práticos 7

    Você precisa procurar o nome de um supermercado em uma listagem e não sabe se este é um mercado, supermercado ou um hipermercado.

  23. Exemplos práticos 7 - Continuação

    • (super|hiper)mercado
    • (su|hi)permercado
    • ((su|hi)per)?mercado
    • Ei! E se tivesse minimercado também?
    • (mini|(su|hi)per)?mercado
  24. Exemplos práticos 8

    (lenta)(mente) é \2 \1

  25. Exemplos práticos 8 - Continuação

    lentamente é mente lenta

  26. Exemplos práticos 9

    ((band)eira)nte \1 \2a

  27. Exemplos práticos 9 - Continuação

    bandeirante bandeira banda

  28. Exemplos práticos 10

    in(d)ol(or) é sem \1\2

  29. Exemplos práticos 10 - Continuação

    indolor é sem dor

  30. Exemplos práticos 11

    ((((a)b)c)d)-1 = \1,\2,\3,\4

  31. Exemplos práticos 11 - Continuação

    abcd-1 = abcd,abc,ab,a

  32. Os 6 mandamentos do Criador

    No mundo das ERs, temos diversas "leis" não escritas que ora ou outra vão bater a sua porta e você verá que segui-las fará com que suas ERs sejam mais precisas e não falhem.

    Essas leis são um misto de dicas de prevenção de problemas e ganhos de performance. Se você está começando, não se preocupe com essas regras. Mas se você já tem uma experiência grande com ERs, verá que essas leis podem lhe poupar estresse.

  33. Não complique

    Ao construir uma ER, lembre-se que um dia alguém, provavelmente você mesmo, terá de dar manutenção a ela, para arrumar algum problema ou incrementá-la. Tendo isso em mente, evite fazer construções complicadas desnecessariamente. Nem sempre a menor ER é a melhor, tudo vai depender do quão comentada ela está ou das habilidades de quem for mantê-la.

    • [0-9]\.[0-9]{3}\.[0-9]{3}-[0-9]
    • [0-9](\.[0-9]{3}){2}-[0-9]

    Então muito cuidado ao colocar grupos dentro de grupos, quantificar grupos, usar chaves quando se pode usar o asterisco, entre outros. Procure manter sua ER simples. Como dizem os gringos: KISS ("Keep It Simple, Stupid"), traduzindo: "deixe simples, estúpido".

  34. Use o circunflexo

    Sempre que possível, comece sua ER com o circunflexo. Como já vimos, o robozinho vai tentando casá-la, caractere por caractere, da esquerda para a direita, a partir do começo da linha. Então, o ponto inicial de pesquisa, é o começo de linha.

    Se você não coloca o circunflexo em sua ER, o robozinho tentará casá-la em qualquer parte da linha. Isso significa ir varrendo a linha, um por um, até chegar no final e caso não encontre o padrão, retorna falha na pesquisa.

    Se você coloca o circunflexo na sua ER, forçando o casamento do começo de linha, se o primeiro componente da ER após o ^ já não casar com o primeiro caractere da linha, dali mesmo já retorna falha de pesquisa, sem precisar varrer o resto da linha.

  35. Evite a lista negada

    A lista negada é um grande aliado quando não se sabe exatamente que tipo de dados estão em uma determinada posição.

    Mas lembre-se: a tabela ASCII tem 255 caracteres. Dizer algo como [^:] significa negar um caractere e permitir outros 254, o que muitas vezes é um exagero.

    Essa abrangência toda pode trazer resultados negativos, casando partes incorretas. Sempre que possível, tente descobrir quais as possibilidades válidas de dados em uma determinada posição e cadastre todas elas dentro de uma lista normal.

    Nesse exemplo, se o tipo de dados que não pode ser os dois pontos forem letras, números e alguns símbolos, liste-os: [A-Za-z0-9,.()%!].

  36. Evite o curinga

    Quando pegamos o jeito com expressões regulares e as usamos regularmente, é comum usar o .* para qualquer situação, pois como todo curinga que se preze, é uma mão na roda. Mas à medida que você vai usando ERs para coisas mais complicadas e mais intensivamente, você começa a perceber que grande parte de seus problemas foi ter usado o curinga guloso e genérico, onde você poderia ter sido mais específico, e ele casou o que não devia.

    Nem sempre é fácil trocar um curinga por outra coisa. Supõe-se que se você já o usou, é porque precisava de "qualquer coisa". Mas pare para pensar, esse qualquer coisa é realmente QUALQUER coisa? Lembre que isso é muito abrangente, o tudo e o nada. Não seria apenas "qualquer letra em qualquer quantidade" ou "quaisquer caracteres fora espaços em branco"?

  37. Evite o curinga - Continuação

    Podemos evitar isso sendo mais específicos em nossa ER. Em vez de dizer <.*>, ou seja, uma marcação pode ter "qualquer coisa" antes do >, dizemos que pode ter "qualquer coisa fora o fechamento da marcação". Invocaremos a lista negada para nos ajudar nessa supertarefa, assim: <[^>]*>, ou mais visual:

    		um <b>negrito</b> aqui.
    		...xxxxxxxxxxxxxx           <.*>
    		...xxx.......xxxx           <[^>]*>
    			
  38. Seja específico

    E agora a regra de ouro, aquela que acaba resumindo as outras, a mãe de todas: seja específico. Memorize bem isso: seja específico. De novo: seja específico.

    Se você sempre tiver esta regra em mente ao construir uma ER, as chances de falha ficam muito reduzidas. Os metacaracteres são vários e servem para criarmos um universo de possibilidades para casarmos um texto, então o quente é fazer um universo restrito, onde todos os componentes fazem sua parte no todo, cada um com seu pedacinho.

    Algumas regrinhas e dicas de como ser específico já foram vistas, mas basicamente para isso, primeiro você deve saber exatamente que tipo de dados procura. Um conhecimento do trecho que se quer casar acontece quando se pode responder a estas três perguntas:

  39. Seja específico - Continuação

    • O que você quer casar?
    • Em que quantidade?
    • Em qual contexto ou posição?

    Sabendo o que se quer, basta traduzir isso para uma ER, lembrando sempre de evitar generalizações como o ponto, o curinga, a lista negada, ignorar maiúsculas e minúsculas, não usar âncoras. Sempre descreva em detalhes suas intenções, delimitando e especificando bem sua ER.

    Em outras palavras, se você está com fome, não diga simplesmente "Quero uma pizza", diga: "Quero uma pizza de calabreza, sem cebola, tamanho médio, cortada em 8 pedaços e com borda de catupiry".

  40. Não seja afobado, seja ninja

    "Encere à direita, lixe à esquerda e pinte para cima e para baixo."

    Vamos ver uma maneira diferente e interessante de mostrar exemplos de expressões regulares: mostrando como funciona o processo criativo, passo a passo. A arte ninja milenar de criar ERs do nada.

    Mentalizando seu objetivo (data, telefone), comece a primeira tentativa tímida e abrangente, usando o ponto para se ter um esqueleto genérico do que se quer casar. Teste a ER assim mesmo.

    Deu certo? Então agora você trocará alguns dos pontos para ser mais específico, de acordo com as regras do tipo de dado que você quer casar. E assim segue, devagar, sempre testando cada modificação e seguindo a passos curtos, com modificações pequenas.

  41. Não seja afobado, seja ninja - Continuação

    Ao chegar em um ponto onde já está bem específico, procure por alternativas, exceções, elas sempre existem. Aquele trecho da ER é realmente obrigatório, não seria opcional? E quando você acha que a ER está pronta, chega um dado novo um pouquinho diferente e você vê que tinha esquecido que aquilo também era válido. Para incrementar a ER, suas armas são os grupos, o ou, o opcional e as chaves.

    Quando sua ER ficar grande e cheia de alternativas, é sinal de que você está conseguindo dizer ao robozinho exatamente o que quer. E assim é que se fazem ERs complicadas Daniel San, de grão em grão!

    Tolo daquele que senta e quer escrever o todo de uma vez! A arte de criar ERs deve ser saboreada, sem pressa, e com inspiração. "Dê um passo após o outro pequeno gafanhoto."

  42. Como desenvolver uma ER

    Data:
    dd/mm/aaaa
    ../../....
    [0-9]{2}/[0-9]{2}/[0-9]{4}
    [0123][0-9]/[0-9]{2}/[0-9]{4}
    [0123][0-9]/[01][0-9]/[0-9]{4}
    [0123][0-9]/[01][0-9]/[12][0-9]{3}
    ([012][0-9]|3[01])/[01][0-9]/[12][0-9]{3}
    ([012][0-9]|3[01])/(0[1-9]|1[012])/[12][0-9]{3}
    (0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[012])/[12][0-9]{3}
  43. Como desenvolver uma ER

    Telefone:
    	...-....
    	[0-9]{3}-[0-9]{4}
    	[0-9]{4}-[0-9]{4}
    	\(..\)[0-9]{4}-[0-9]{4}
    	\(..\) ?[0-9]{4}-[0-9]{4}
    	\(0xx..\) ?[0-9]{4}-[0-9]{4}
    	\(0xx[0-9]{2}\) ?[0-9]{4}-[0-9]{4}
    	(\(0xx[0-9]{2}\) ?)?[0-9]{4}-[0-9]{4}
  44. Outros Exemplos de RegExp

    • ^(0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[012])/[1-3][0-9]{3}$
    • ^[a-zA-Z0-9_\.-]{2,}@([A-Za-z0-9_-]{2,}\.)+[A-Za-z]{2,4}$
    • ^([0-1][0-9]|[2][0-3]):[0-5][0-9]$
    • ^\d{0,}$
    • ^\(\d{2}\) \d{4}-\d{4}$
    • ^(\d{3})\.(\d{3})\.(\d{3})-(\d{2})$ ou ^((\d{3})\.){2}(\d{3})-(\d{2})$ Poderia? ^(\d{3})\.\1\.\1-(\d{2})$ ou ^((\d{3})\.)\1\2-(\d{2})$
    • <[iI][mM][gG])([^s|S]*)([sS][rR][cC]=\"[^\"]*\")([^>]*>
    • ((http|https|ftp|mailto):)?(//)? (\w+([\.@]\w+)*?)(?:/|@)?([^\"\?]*?)?(?:\?([^\?\"]*?))?([^;:\(\)#])$
  45. Curiosidades

    Expressões Regulares e Linguagens Regulares

    • Um Autómato Finito (AFD ou AFND) descreve uma Linguagem.
    • Uma Expressão Regular (ER) é a formalização algébrica de um Autómato Finito.
    • A linguagem descrita por uma Expressão Regular E chama-se Linguagem Regular e denota-se por L(E).
    • Em todos os comandos que envolvem a pesquisa de palavras (tais como o grep do Unix) o padrão é definido por uma ER que é convertida no correspondente AF cujo funcionamento é simulado sobre o(s) ficheiro(s). Geradores de Analisadores Léxicos, tais como o Lex ou o Flex constroem AFD’s a partir de definições de "símbolos terminais" descritos por ER’s.
  46. Referências

  47. Dúvidas?

    Confira algumas explicações no artigo Workshop "Expressões Regulares".

    Mande um e-mail, que te responderei com o maior prazer.