Regex é legal - Alberto Monteiro, C# developer
Inicio » .NET » Regex é legal
Hoje vou abordar um assunto no qual gosto, Regular Expressions, também conhecido como Regex, e na minha opinião não é um bixo de sete cabeças. É comum eu ler comentários de colegas de profissão dizendo: "Escreva uma vez, não entenda nunca mais", e na minha humilde opinião não é por ai. Regex é uma linguagem na qual podemos aprender, creio que esses casos que as pessoas não entendem nunca mais uma regex, é pelo simples fato de não conhecer a linguagem e simplesmente:
Não entender a solução.
Regex possui uma sintaxe como qualquer outra linguagem e se não aprendermos ela, realmente nunca iremos entender uma regex, enfim a culpa é devido a incompetencia do desenvolvedor.
Certa vez vi uma expressão regular, que de acordo com o autor dela servia para identificar urls que não possuem o "www.", por exemplo:
A regex em questão era a seguinte:
^((http|https)://[^www]).*$
Porem existe uma problemática nessa url, ela não faz exatamente o que ela foi incumbida a fazer, em um caso com uma url assim: http://wordpress.com, essa regex retornaria falha, mas não temos o www. então a regex está errada. E o pior de tudo é que ela funciona em muitos outros casos, como os citado acima.
Vamos analisar parte por parte dessa regex.
Primeira parte => ^((http|https)://
Essa parte indica que queremos que nossa string comece com http:// ou https://.
Nós podemos melhorar essa regex dessa maneira:
Quando usamos parenteses em uma regex, nos estamos definindo um grupo, e quando temos o pipe(|) dentro do grupo, significa que temos a condição "OU" , sendo assim, http ou https. Mas o proposito da regex não faz necessario termos esse grupo, então simplificamos ele, e tivemos o mesmo resultado trocando todos os parenteses e o pipe por um simples "s?". O simbolo de interrogação(?) indica que a regra anterior é opcional, no qual a regra anterior é um "s" apos http.
Segunda parte => [^www]
É aqui onde está o perigo! Essa regex é semelhante a essa:
Essa regex diz que não podemos ter um "w" depois da regra anterior, que é o a existência do http:// ou https://. Quando usamos os colchetes "[]", estamos definindo uma cadeia de caracteres que são ou não aceitos, quando eles não são aceitos usamos o simbolo circunflexo "^" para negar a existência deles, segue alguns exemplos:
^[0-9]+$ => Permitimos somente números na string.
^[A-Za-z]+$ => Permitimos somente letras maiúsculas ou minusculas.
^[\w]+$ => Permitimos somente letras(maiúsculas e/ou minusculas) e/ou números.
^[^0-9]+$ => Permitimos qualquer caractere que não seja um número, o que não quer dizer que essa regex é semelhante a regex acima, elas podem resultar em um resultado igual.
Como vemos nesse ultimo exemplo podemos dizer que duas regex dão um mesmo resultado pelo fato de não conhecermos a linguagem, como vimos na primeira parte, temos 2 regex que dão o mesmo resultado, repetindo novamente:
^((http|https)://) == ^https?)://
Mas e agora, como fazer uma regex que informe se o http(s):// não é seguido de "www.".
Para chegarmos ao nosso objetivo vou usar o chamado lookahead um recurso brilhante das expressões regulares. O lookahead nada mais é que essa determinada regra não deve existir apos a regra anterior, sendo assim a nossa regex ficaria dessa forma:
^https?://(?!www[.]).+$
Para atingir nosso real objetivo, trocamos [^www] por (?!www[.]), com isso, aplicando na regex antiga ficaria assim:
((http|https)://[^www]).*$
Que retorna o mesmo resultado para regex anterior a ela, mas o problema dessa regex é como um código ruim com variáveis não utilizadas que nesse caso é o excesso de parenteses e a existência ou não do "s" que ao invés de usar grupo pode facilmente ser substituída pelo caractere opcional usando o "?".
Como vimos na definição da wikipedia, a regex é interpretada por um processador, e existem diferente tipos de processadores de regex, o processador de regex do .NET não é igual ao processador em Javascript, mas graças ao POSIX que é o padronizador de expressoes regulares, essa preocupação é absurdamente reduzida, enfim para ilustrar uma situação que isso acontece temos uma regex com um grupo nomeado:
^\d{2}/\d{2}/(?<ano>\d{4})$
Em C# essa expressão regular é aceita, e inclusive podemos acessar esse grupo de forma fácil:
[csharp]string strRegex = @"^\d{2}/\d{2}/(?<ano>\d{4})$";
string strTargetString = @"25/02/1800";
Console.WriteLine(myMatch.Groups["ano"].Value);
Já em javascript, a sua execução retornaria um erro, já que ele não aceita grupos nomeados
/^\d{2}/\d{2}/(?<ano>\d{4})$/.test("25/02/1800")
SyntaxError: Invalid regular expression: /^\d{2}\/\d{2}\/(?<ano>\d{4})$/: Invalid group
Olá Alberto tudo bem?
Estou aprendendo expressão regular e ainda tenho algumas dúvidas…
Utilizo o CrazyEgg para algumas análises e ele trabalha com Regex para URL, meu problema é o seguinte.
Tenho uma URL fixa http://www.blabla.com.br/brubru
A partir dessa principal pode-se ser direcionado para outras páginas …
O que eu preciso é montar uma Regex que não tenha a expressão "zero-resultado" e que tenha a expressão "c-" pode me ajudar?
Eu não entendi muito bem o seu caso, se você quiser me enviar por email explicando melhor o caso, e me dar um exemplo do que a regex vai aceitar e recursar seria otimo. Meu email para contato é o alberto.monteiro[at]live.com(troca o [at] por @)