Você está na página 1de 9

Expresses Regulares

Primeiramente o que uma Expresso Regular?


Expresso Regular no so apenas aqueles pequenos conjuntos de
caracteres que geralmente resolvem os maiores e mais difceis
problemas do cotidiano no desenvolvimento de software. Como o
prprio nome diz, Regular nos vem algo que no foge a regra, regra
no caso definida pelas Expresses. Logo Expresses Regulares podem
ser definidas com mtodos formais para especificar padres
encontrados nesses textos.
Algo que regular s nos retorna dois valores, verdadeiro ou falso,
no existe o padro meio-termo. Sendo assim podemos fazer
verificaes utilizando ERs para saber se determinado texto condiz
(Casar, do ingls Match) com determinado padro especificado
anteriormente.
Com ERs podemos validar todo dado que segue padres tal como email que tem como padro (texto arroba texto ponto texto), tomando
texto como sendo no necessariamente literal. Dentre os usos de
Expresses Regulares podemos destacar tambm na validao de
CPF, RG, diversos protocolos como http e ftp, tags de marcao,
cartes de crdito e etc...
Quais as desvantagens das Expresses Regulares?
ERs parece ser a resposta para todos os seus problemas, no? Errado,
ela pode ser o seu problema se usada de maneira errada e/ou de
maneira demasiada. O grande poder das Expresses Regulares pode
custar muito caro na performance da sua soluo pois consome
bastante tempo e memria, tornando a navegao lenta, o ideal
evitar o seu uso se existirem alternativas disponveis.
Outra varivel no uso de expresses regulares o tamanho do seu
projeto, em um site por exemplo, que contm poucas visitas dirias, o
uso de expresses regulares no custar tanto, porm um site com
vrias requisies simultneas seria prejudicado, pois voc ter muito
processamento agregado em ERs.
Por exemplo, se for necessrio verificar se uma varivel contm @
(arroba) ao invs de usarmos ERs podemos fazer uma verificao
simples com strpos(), strstr(),..
<?php
$texto="ola@mundo";
$existe=strpos($texto,"@");
if($existe===false){
//noexistearrobanotexto

}
else{
//existearrobanotexto,eestanaposio$existe
}
?>

ApacheBench: Poderiamos usar o programa disponibilizado pelo


Apache para fazer benchmarking chamado ab (ApacheBench)
encontrado facilmente dentro do diretrio bin do seu apache, com ele
teramos uma viso ampla podendo setar centenas de request's com
concorrncia entre outros atributos interessantes, porm isso vale um
outro artigo baseando-se na complexidade do assunto. Vamos fazer o
benchmarking com o PHP pois podemos limitar precisamente o local
que queremos analisar.
Falando em PHP, uma maneira funcional de calcular a diferena de
performance utilizando ERs e uma verificao simples o uso da
funo microtime() do PHP, como vemos abaixo.
Calculando o tempo gasto na checagem de padro
manualmente:
<?php
ob_start();
// atribui o tempo inicial
$inicial = microtime();
$texto = "ola@mundo.com";
strpos($texto,"@");
// atribui o tempo final
$final = microtime();
/* calcula a diferena entre final e inicial
o valor retornado pela funo microtime() em milissegundos
ento multiplicamos por 1000 para obter o valor em segundos */
echo "Tempo gasto: ".(($final - $inicial)*1000)." segundos.";
?>

O valor retornado poder variar cada vez que atualizar a pgina, pois
o processador pode estar processando outras threads, o retorno
mdio no meu computador foi de (0.058 segundos) para encontrar a
primeira ocorrncia de arroba na varivel "ola@mundo".
Calculando o tempo gasto na checagem de padro usando
Expresses Regulares:
<?php
ob_start();

// atribui o tempo inicial


$inicial = microtime();
$texto = "ola@mundo";
// Expresso Regular utilizada para checar a presena de arroba
$er = '/(.*)?@(.*)?/';
preg_match($er,$texto);
// atribui o tempo final
$final = microtime();
$tempo = ($final - $inicial)*1000;
/* calcula a diferena entre final e inicial
o valor retornado pela funo microtime() e milisegundos
ento multiplicamos por 1000 para obter o valor em segundos */
echo "Tempo gasto: .$tempo. segundos.";
?>

O retorno mdio no meu computador foi de (0.090 segundos) para


encontrar a primeira ocorrncia de arroba na varivel "ola@mundo".
Podemos ver que o tempo de processamento quase o dobro, sendo:
Maneira Alternativa: 0.058 segundos
Expresses Regulares: 0.090 segundos
Essa diferena de tempo aumenta de acordo com a dificuldade da
operao realiza, se o nosso texto tivesse 400 linhas, a diferena de
tempo seria gritante, fica como exerccio para vocs fazerem os
testes de performance (benchmarking).
Vamos ao estudo das expresses, eu recomendo para estudo a
prtica das expresses, pois assim como linguagem de programao
ERs s se aprende fazendo.
Essas expresses vistas singularmente tambm podem ser chamadas
de metacaracteres.
Como o nosso conhecimento em ERs bastante limitado at agora,
no podemos ainda criar expresses (Composio de Metacatacteres)
ento iremos nos restringir a exemplos bem simples.
PHP trabalha com dois tipos diferentes de expresso regular sendo
POSIX e Perl-Compatible. POSIX menos poderosa e as vezes mais
lenta que as expresses Perl-Compatible porm pode ser mais fcil de
utilizar. Ns usaremos Perl-Compatible pois tambm usaremos esse
padro no artigo de mod_rewrite.

A funo para expresses regulares Perl-Compatible no php


preg_match() e para POSIX ereg()

1) O metacaracter circunflexo ^:
O circunflexo representa o comeo da string. Por exemplo, se
quisermos saber se determinado texto comea com 'abc' poderemos
prosseguir da seguinte maneira:
<?php
// Texto alvo
$texto = "abcdefgh";
// Ao adicionarmos o modificador i no final dizemos
// que a comparao deve ser case-insensitive
$er = '/^abc/i';
if(preg_match($er,$texto)) {
echo "Comea com abc";
}
else {
echo "No comea com abc";
}
?>

2) O metacaracter ponto . :
O ponto implica no fato de aceitar qualquer caracter em determinada
posio. Por exemplo, se fossemos brincar com a palavra PHP
aceitando como vlido o H ser qualquer coisa, P(qualquer caracter)P
faremos:
<?php
$texto = "PUP";
$er = '/P.P/i';
if(preg_match($er,$texto))
echo "PUP vlido com o padro estabelecido pela ERs";
else
echo "PUP no vlido com o padro estabelecido pela ERs";
?>

3) O metacaracter Cifro $:
Semelhante ao circunflexo, porm atua na verificao no final da
string, se quisermos saber se alm de comear com 'abc' a string
termina com 'xyz' poderemos prosseguir da seguinte maneira:
<?php
$texto = "abcxyz";
$er = '/^(abc)(xyz)$/i';
echo (preg_match($er,$texto))? 'vlido' : 'invlido';
?>

4) Os metacaracteres asterisco, mais, interrogao e chaves *


+ ? {}:
Os quatro metacaracteres so multiplicadores de ocorrncias.
I) O multiplicador asterisco * indica que o caractere que esta antes
dele poder ocorrer 0 (zero) ou infinitas vezes.
II) O multiplicador + indica que o caractere anterior poder ocorrer 1
(uma) ou infinitas vezes (porm necessariamente uma vez).
III) O multiplicador binrio ? indica que o caractere anterior poder
ocorrer 1 (uma) ou 0 (zero) vezes, ou seja, poder existir ou no.
IV) O multiplicador {} funciona de maneira explicita, sendo que
podemos ou no, definir o nmero de repeties. Por exemplo:
Exemplos
a{n} indica que a deve ocorrer exatamente 'n' vezes. Ex: a{3} = aaa
a{n,m} indica que a deve ocorrer pelo menos 'n' vezes e no mais
que 'm' vezes. Ex: a{3,6} = aaaaa
a{n,} indica que a deve ocorrer pelo menos n vezes. Ex: a{3,} =
aaaaaaa

Sendo assim, agora podemos permitir mais valores entre 'abc' e 'xyz'
com a ajuda do metacaracter ponto que aceita qualquer coisa e
usando multiplicidade, poderemos prosseguir da seguinte maneira:
<?php
$texto = "abcdefghijkmnopqrstuvwxyz";
// Indicamos que alm de comear com abc e
// terminar com xyz, poder existir 0 (zero) ou
// mais caracteres nesse intervalo
$er = '/^abc(.*)xyz$/i';
echo (preg_match($er,$texto))? 'vlido' : 'invlido';
?>

Nota: Perceba que (.+)? semelhante a (.*), sendo que o + (mais)


obriga que o . (ponto) acontea pelo menos uma vez, porm o
metacatacter ? indica que isso no necessariamente precisar
acontecer.
5) A lista [] e Grupos ():
As listas e grupos permitem que voc defina um espao amostral. Por
exemplo, se quisermos saber se um registro comea com vogais
poderemos usar a lista junto com o circunflexo, dessa maneira
^[aeiou] onde ir casar com palavras como "arquitetura","email","inteligncia" e etc..
Intervalo em Listas: Utilizando um hfen podemos definir intervalos
baseando-se na tabela ASCII como ordem oficial, ou seja, [0-9] indica
todos os digitos de 0 at 9 [0123456789] o mesmo com letras [a-z]
para todas as minusculas [A-Z] para todas as maiusculas e [a-zA-Z]
para os dois simultaneamente.
Com o mesmo circunflexo podemos negar a lista, apenas colocando-o
dentro da lista [^aeiou] assim, ser vlido iniciar com qualquer
consoante.
Perceba que a lista s retorna 1 (um) catacter, podemos resolver isso
utilizando os Grupos () e utilizando o delimitador "Ou" | (http:|https:|
ftp:) Assim poderemos validar esses protocolos da seguinte maneira:
Nota: No possvel negar um grupo utilizando o circunflexo. Para
fazer a negao utilize ! (exclamao) !^(http:|https:|ftp:)
^(http:|https:|ftp:) em PHP:
<?php

$texto = "http://www.rafaelcapucho.com";
$er = '/^(http:|https:|ftp:)/i';
echo (preg_match($er,$texto))? 'vlido' : 'invlido';
?>

^(http:|https:|ftp:) em Python:
import re
texto = 'http://www.rafaelcapucho.com'
// re.match para comparao re.match(Padrao,String,[bandeiras])
if(re.match('^(http:|https:|ftp:)',texto,re.IGNORECASE)):
print('vlido')
else:
print('invlido')

Nota: Se for preciso utilizar barras nas expresses regulares dentro de


funes devemos escap-las com a contra-barra. \
I) Estudo de Caso - Validando e-mail com Expresso Regulares
Agora que ns j conhecemos os principais metacaracteres podemos
comear a brincar com eles, vamos aos estudos de caso, como
poderemos proceder para validar um endereo eletrnico? Primeiro
devemos analisar, o padro estabelecido que no caso seria algo
como:
texto @ texto ponto texto
Como no podemos saber quantos caracteres tem os textos
previamente, devemos utilizar multiplicadores, devemos multiplicar o
metacaracter . (ponto) pois ele casar com qualquer coisa.
Usaremos o multiplicador + (mais) pois o nosso texto deve ter pelo
menos 1 caractere, sendo assim temos algo como (.*).
Aplicando ao padro temos algo como: (.+)@(.+).(.+) perceba que
no podemos utilizar o . (ponto) para representar um ponto literal
pois ele ser tratado como metacaracter ento escapamos ele com
uma contra-barra \. Teremos:
(.+)@(.+)\.(.+) Estamos esperando o que para testar?
(.+)@(.+)\.(.+) em PHP:

<?php

$texto = "palavra@provedor.com";
$er = '/(.+)@(.+)\.(.+)/i';
echo (preg_match($er,$texto))? 'vlido' : 'invlido';

?>

(.+)@(.+)\.(.+) em Python:
import re
texto = 'palavra@provedor.com'
// re.match para comparao re.match(Padrao,String,[bandeiras])
if(re.match('(.+)@(.+)\.(.+)',texto,re.IGNORECASE)):
print('email vlido')
else:
print('email invlido')

II) Estudo de Caso - Removendo Tags com Expresso


Regulares
Primeiramente devemos analisar o padro estabelecido pelas Tags,
escolhi para o exemplo Tags HTML pela familiaridade que muitos tem
com esse padro, mapeando teremos algo como:
texto <tag> texto </tag> texto

A idia remover as tags, todas as tags independente do texto


dentro da tag, ou seja, devemos remover tudo que estiver entre <>
seja l o que estiver escrito.
Se no sabemos previamente o que estar dentro das Tags HTML,
podemos representar com a multiplicao indefinida de qualquer
catactere .*, que deve estar dentro das Tags, algo como:
<.*?>
Observao: Analisando essa expresso chegamos a algumas
questo, tal como, porque usar o multiplicador * (asterisco) ao invs
do + (mais)? Escolhemos o * (asterisco) porque tambm queremos
remover tags vazias como essa <>, se usssemos o multiplicador +
(mais) s removeramos tags que contm pelo menos 1 (um)
caractere dentro das tags
Removendo Tags com PHP e Expresses Regulares:

<?php
$texto = "texto1<strong>texto2</strong>texto3";
$er = '/<.+?>/i';
// Funo preg_replace(pattern, replacement, subject [, limit ]);
echo $novoTexto = preg_replace($er,"",$texto);
?>

A sada do cdigo acima ser: texto1texto2texto3 onde trocamos


todas as tags encontradas pelo contedo expresso pelo segundo
parmetro da funo preg_replace().
Removendo Tags com Python e Expresses Regulares:
import re
texto = 'texto1<strong>texto2</strong>texto3'
// Compila a ER com a flag IGNORECASE
padrao = re.compile('<.*?>',re.IGNORECASE)
// Baseando no padrao, substitui o primeiro parametro
// no segundo parametro
novoTexto = padrao.sub("",texto)
print(novoTexto)

Performance: Entretanto como analisamos anteriormente devemos


evitar usar ER. Poderamos criar uma lista de tags e mandar substitulas utilizando str_replace() ao invs de preg_replace(). Assim
ganhamos muito com performance.
Com esse artigo j temos uma viso considervel sobre ER para
utilizarmos no artigo sobre mod_rewrite e outras aplicaes.
Dessa maneira, termino esse artigo sobre Expresses Regulares em
caso de dvidas, entre em contato! Bom proveito!

Você também pode gostar