Informática Numaboa - Tutoriais e Programação
Encontrando números com regex
Sab 25 Ago 2007 22:00 |
- Detalhes
- Categoria: REGEX - Expressões Regulares
- Atualização: Domingo, 06 Dezembro 2009 13:23
- Autor: vovó Vicki
- Acessos: 12438
Como as expressões regulares lidam basicamente com caracteres, encontrar números acaba dando um pouco mais de trabalho do que se imagina inicialmente.
Não se pode simplesmente escrever [0-255] para encontrar um número que vai de 0 a 255 - isto dá caca Apesar de ser uma expressão regular perfeitamente válida, o resultado não é bem o que se espera se não se souber o que esta regex está pedindo. Então vamos lá:
Usando colchetes, definimos uma classe de caracteres. Esta classe de caracteres contém 0-2, além dos caracteres 55. O hífen indica uma sequência e foi colocado entre 0 e 2, ou seja, corresponde aos algarismos 0, 1 e 2. A sequência é complementada por 55, o que é chover no molhado porque não é preciso definir mais de uma vez um caractere dentro de uma sequência. Bem, para encurtar a história, a classe de caracteres "explícita" é [0125] e, é claro, não podemos exigir que esta classe encontre outros números além de 0, 1, 2 e 5.
O pulo do gato
Como as expressões regulares lidam apenas com texto, o motor regex trata 0 como um único caracter e 255 como três caracteres. A conclusão óbvia é que estamos procurando uma regex que encontre combinações de um a três caracteres.
A regex com uma classe de caracteres [0-9] consegue localizar números de 0 a 9. Da mesma forma, uma regex com as classes de caracteres [1-9][0-9] consegue achar números de 10 a 99. Até aí, tudo bem. Esta é a parte fácil. Para encontrar números com três dígitos a coisa é um pouco mais complicada porque será preciso descartar os números de 256 a 999 (se é que, depois de tanta explicação, você ainda se lembra que a tarefa é achar números de 0 a 255 ).
Pois bem. Combinando caracteres literais com classes de caracteres, a regex 1[0-9][0-9] isola os números de 100 a 199 e a regex 2[0-4][0-9] isola os números de 200 a 249. Putz... já deu para achar uma luz para os números de 0 a 249, só faltam os de 250 a 255. Então, vamos lá! Sabendo manobrar as classes de caracteres, não é nenhum bicho de sete cabeças descobrir que 25[0-5] corresponde aos números de 250 a 255.
O que conseguimos fazer até agora foi "quebrar" o problema em problemas menores. Como não deixaram de ser problemas e, como por definição cada problema tem uma solução, basta "costurar" as soluções dos problemas fracionados para chegar à solução final. Aqui estão os "pedaços" encontrados:
[0-9] algarismos de 0 a 9 [1-9][0-9] algarismos de 10 a 99 1[0-9][0-9] algarismos de 100 a 199 2[0-4][0-9] algarismos de 200 a 249 25[0-5] algarismos de 250 a 255
AHÁ!!! Estamos quase lá. Agora é só usar algumas alternativas para que a regex funcione como esperado. Alternativas em regex significam "ou". Se você leu o tutorial REGEX - Caracteres ainda deve se lembrar da história do gato|rato... se não souber do que estou falando, é melhor dar uma espiada antes de continuar.
Bão, partindo do pressuposto de que você saiba usar alternativas em regex, a expressão a seguir é o pulo do gato que estávamos procurando:
[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]
com um pequeno senão (sempre precisa existir um senão para melar :thumbdown: ): esta regex também isola "123" se o texto tiver "12345". Putz, ainda falta um pouquinho... mas não desanime, estamos quase chegando lá. Considere o "número" como uma "palavra" e indique os limites com \b sem esquecer de colocar as classes de caracteres entre parênteses para agrupar as alternativas:
\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b
Agora, se você estiver validando uma entrada de dados (num formulário, por exemplo), use âncoras:
^([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$
Finalmentes
Para completar este exemplo, seguem mais alguns para encontrar outras sequências de algarismos que são muito comuns:
- 000 a 255: ^([01][0-9][0-9]|2[0-4][0-9]|25[0-5])$
- 0 ou 000 a 255: ^([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$
- 0 ou 000 a 127: ^(0?[0-9]?[0-9]|1[0-1][0-9]|12[0-7])$
- 0 a 999: ^([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$
- 000 a 999: ^[0-9]{3}$
- 0 ou 000 a 999: ^[0-9]{1,3}$
- 1 a 999: ^([1-9]|[1-9][0-9]|[1-9][0-9][0-9])$
- 001 a 999: ^(00[1-9]|0[1-9][0-9]|[1-9][0-9][0-9])$
- 1 ou 001 a 999: ^(0{0,2}[1-9]|0?[1-9][0-9]|[1-9][0-9][0-9])$
- 0 ou 00 a 59: ^(0?[0-9]?[0-9]|1[0-1][0-9]|12[0-7])$
- 0 ou 000 a 366: ^(0?[0-9]?[0-9]|[1-2][0-9][0-9]|3[0-6][0-9]|36[0-6])$
Referências
- :us: Regular Expressions (em inglês)
- :us: Zvon Regexp (em inglês, com muitos exemplos)