No primeiro artigo sobre expressões regulares eu fiz uma introdução bem superficial sobre alguns pontos, na verdade batemos conversamos um pouco sobre o assunto.

Hoje, vamos ver mais alguns pontos e entender algumas coisas contidas dentro de uma ER.

Eu utilizo um aplicativo bem pequeno para criar e testar minhas ERs, ele é free e bem fácil de ser utilizado, para quem quiser fazer o download basta entrar em http://laurent.riesterer.free.fr/regexp/ lá tem atualmente 2 versões, eu utilizo a 3.1.

No momento vamos nos focar na ER em si e não na aplicação dentro do projeto C#, vamos criar essa ER aos pouco e vamos chegar a um resultado esperado.

Uma data tem partes simples de entender, por exemplo, os meses que vão de “01” até “12” nada a mais e nada a menos, temos também os dias que vão de “01” até “28”, “30” ou “31” e por fim os anos que neste momento não vamos nos preocupar.

Uma data valida seria “31/12/2010”, vamos pegar o dia para analisarmos:

1º) No dia podemos observar que o primeiro digito pode ser “0”, “1”, “2” ou “3” e no segundo digito podemos ter de “0” a “9”.

2º) Quando o primeiro digito é “3” só podemos ter no segundo digito o “0” e o “1”.

3º) Quando o primeiro digito é “0” não podemos ter no segundo outro “0”.

Agora vamos analisar o mês.

1º) No primeiro digito podemos ter “0” e “1”.

2º) Quando o primeiro digito é “0” podemos ter no segundo de “1” a “9”.

3º) Quando o primeiro digito é “1” podemos ter no segundo de “0” a “2”.

Tendo esses dados vamos criar uma ER simples sem nos preocuparmos tento com as regras acima e depois vamos parte por parte.

EX1: “\d\d/\d\d/\d\d\d\d”

Nesse exemplo validaremos/casaremos todo conjunto de caracteres que atender esse padrão. Que a primeira vista é confusa e complicada, mas não é. “\d” como já sabemos mapeia qualquer caractere que seja digito, então temos um digito seguido de outro digito seguido por barra “/” seguido de mais 2 dígitos seguidos de uma barra “/” seguidos de mais 4 dígitos. Essa ER casa com “00/00/0000”, “99/99/9999” e “12/34/5678” e não casa com “AA/BB/dddd”.

Mas temos os operadores quantitativos que nos ajudam a informar quantas vezes deve ser mapeado sem ter que ficar colocando “\d” varias vezes para obter esse resultado, imagina se precisássemos validar “0123456789-0987654321” quantos “\d” teríamos que colocar. Para validarmos esse valor/formato podemos escrever uma ER assim “\d{10}-\d{10}”.

Onde “{10}” informa quantas vezes “\d” deve aparecer antes do “-“ e quantas vezes deve aparecer depois.

Vamos refatorar nosso EX1.

Ficando: “\d{2}/\d{2}/\d{4}”, ai temos uma ER que diz 2 dígitos seguidos de barra “/” seguidos de 2 dígitos seguidos de barra “/” seguidos de 4 dígitos, mudamos a ER mais o resultado esperado é o mesmo.

Só lembrando que temos uma lista acima de regras que observamos para a data, então vamos para o primeiro, onde diz quais valores podemos ter para o dia, mas antes vamos refatorar mais uma vez nossa ER, criando os agrupamentos e substituindo “\d” pelo conjunto “[0-9]”.

Ficando: “([0-9]{2})/([0-9]{2})/([0-9]{4})”

Agora sim vamos ajustar nossa ER para alem de validar o formato validar os valores do dia “([0-3][0-9])/([0-9]{2})/([0-9]{4})” desta forma o “99/99/9999” não casa mais.

Vamos pegar agora a parte que fala a regra para o mês “([0-3][0-9])/([01][0-9])/([0-9]{4})” agora o valor “00/20/2010” não casa mais.

É importante criar passo a passo a sua ER e ir validando se está ocorrendo como você deseja.

Estamos em um ponto que a refatoração vai ser mais complicada por isso temos que ter mais atenção, pois temos a regra que quando “0” no primeiro não podemos permitir “0” no segundo, quando “1” ou “2” podemos ter “0” a “9” e quando “3” podemos ter “0” e “1”, vamos colocar em pratica o uso do “|” (ou). Nossa ER vai ficar assim “(0[1-9]|[12][0-9]|3[01])/([01][0-9])/([0-9]{4})” colocamos 3 opções no para o primeiro grupo separados por “|”(ou), no primeiro permitimos “0” seguido de “1” a “9”, no segundo permitimos “1” e “2” seguidos de “0” a “9”e por ultimo “3” seguido por “0” ou “1”.

Praticamente terminamos a validação do dia.

Vamos agora para a validação do mês, lembrando que o primeiro digito pode ser “0” e “1”, quando “0” o segundo poder ser de “1” a “9” e quando o primeiro for “1” podemos ter somente “0”,”1” e “2”, refatorando nossa ER temos “(0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[0-2])/([0-9]{4})”, mais uma vez utilizamos “|”(ou) só que desta vez no 2 grupo, onde dizemos que se o primeiro digito for “0” seguido de “1” a “9” ou “1” seguido de “0” a “2”.

Agora já validamos o dia e o mês dentro da ER, mais inda esta sendo permitido o ano “0000” e isso não é legal.

Vamos assumir que o ano mínimo permitido seja 1200, então temos uma nova regra para construir na ER, não permitir ano menor que 1200, mas como dizer isso na ER? Não dá, temo que dizer o que pode, então vamos dizer que pode “1” seguido de “2” a “9” seguido de “0” a “9” seguido de “0” a “9” e um “|”(ou) permitindo de “2” a “9” seguido de “0” a “9” seguido de “0” a “9” seguido de “0” a “9”, então temos a seguinte ER “(0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[0-2])/((1[2-9]|[2-9][0-9])[0-9]{2})”.

No ponto em que estamos já esta bem aceitável a validação, mesmo que ainda existem falhas, por exemplo, a data “29/02/2010” vai passar e essa data é uma data invalida, pois 2010 não é bissexto, para construirmos uma ER com esse nível de detalhe teremos que ter 4 “|”(ou) principais onde cada um individualmente trata uma data como uma regra, os outros são praticamente o que fizemos aqui levando em consideração os meses “01”,”03” ,”04” ,”05” ,”05” ,”06” ,”07” ,”08” ,”09” ,”10” ,”11” e “12” deixando o mês “02” para a outra parte do “ou” onde trata os anos bissextos.

Eu tenho aqui essa ER completa vamos ver ela de 2 formas:

Plana: “^(((0[1-9]|[12]\d|3[01])\/(0[13578]|1[02])\/((19|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\/(0[13456789]|1[012])\/((19|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\/02\/((19|[2-9]\d)\d{2}))|(29\/02\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$” , quando você precisar deve utilizar desta forma.

E ela fatiada, que fica melhor para entender como foi desenvolvida:

“^(

                ((0[1-9]|[12]\d|3[01])\/(0[13578]|1[02])\/((19|[2-9]\d)\d{2}))                                                    <- 1º

                |

                ((0[1-9]|[12]\d|30)\/(0[13456789]|1[012])\/((19|[2-9]\d)\d{2}))                                                 <- 2º

                |

                ((0[1-9]|1\d|2[0-8])\/02\/((19|[2-9]\d)\d{2}))                                                                                               <- 3º

                |

                (29\/02\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)))                <- 4º

)$”

Vamos dar uma olhada na nossa timeline do desenvolvimento da ER

1.       “\d\d/\d\d/\d\d\d\d”

2.       “\d{2}/\d{2}/\d{4}”

3.       “[0-9]{2}/[0-9]{2}/[0-9]{4}”

4.       “([0-3][0-9])/([01][0-9])/([0-9]{4})”

5.       “(0[1-9]|[12][0-9]|3[01])/([01][0-9])/([0-9]{4})”

6.       “(0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[0-2])/([0-9]{4})”

7.       “(0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[0-2])/((1[2-9]|[2-9][0-9])[0-9]{2})”

Vocês podem também utilizar os operadores “^” e “$” para indicar que a data deve estar iniciando e terminando a string ficando assim a nossa ER “^0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[0-2])/((1[2-9]|[2-9][0-9])[0-9]{2})$” só lembrando que essa valida todos os dia 29/02 de todos os anos.

Por fim, vamos criar uma aplicação “console Application” com um loop onde iniciaremos nossa data em “01/01/0001” e vamos até “31/12/1199” para ver quais datas vão ser validadas e caso validadas será considerado um erro na ER, o outro loop com a data iniciando em “01/01/1200” e vamos até “31/01/1200” para ver quais datas não vão ser validadas e caso alguma não valide temos outro erro, com isso veremos se ha mais problemas a não ser o dia “29/02”, bom eu espero que não tenhamos mais problemas com nossa ER.

Para você ver e fazer os testes faça o download do arquivo disponibilizado.

Por hoje ficaremos por aqui, voltaremos a falar mais sobre ER.

Até a próxima, ahh não se esqueçam de fazer o download.