Tutorial 1-f

Regular Expressions - função ereg()

        Em quase todos os programas PHP verificaremos a utilização da função ereg() ou alguma de suas "irmãs" : a função ereg_replace(), eregi(), eregi_replace, split() e spliti(). O programador que vem do mundo Windows com certeza tem dificuldades para entender as linhas de código que utilizam estas funções (este é o meu caso). Quem vem do mundo Unix muito provavelmente já conhece a função, que nada mais é do que a implantação do comando regex deste sistema operacional.

        A possibilidade de utilização destas funções é bastante extensa. Vamos nos concentrar aqui a estudar apenas as partes mais importantes, que veremos normalmente na programação em PHP. Para um estudo mais profundo é recomendada a leitura das páginas do manual do comando regex no Unix (ou Linux).

        Para simplificar, vamos estudar com exemplos:

Arquivo: tutorial11.php
<html>
<body>

<form method="post" action="<?php echo $PHP_SELF; ?>">
Texto: <input type=text name="texto" value="
<?php echo isset($texto) ? $texto : "" ?>
">
<input type=submit value="Aperte o botão !">
</form>

<?php

if (isset($texto)) {
  echo "O texto :<BR>";
  echo (ereg("a", $texto) ? "tem ao menos uma letra a minúscula" :
    "não tem nenhuma letra a minúscula") . "<BR>";
  echo (ereg("^a", $texto) ? "" : "não ") . "inicia com a letra a <BR>";
  echo (ereg("a$", $texto) ? "" : "não ") . "termina com a letra a<BR>";
  echo (eregi("php", $texto) ? "" : "não ") .
    "inicia com as letras php, maiúsculas ou minúsculas<BR>";
  echo (eregi("^php", $texto) ? "" : "não ") .
    "inicia com as letras php, maiúsculas ou minúsculas<BR>";
  echo (ereg("^[0-9]", $texto) ? "" : "não ") . " inicia com um número <BR>";
  echo (ereg("^[a-g]", $texto) ? "" : "não ") .
    " inicia com uma letra entre 'a' e 'g' minúscula<BR>";
  echo (eregi("^[a-g]", $texto) ? "" : "não ") .
    " inicia com uma letra entre 'a' e 'g' , maiúscula ou minúscula<BR>";
  echo (ereg("^[a-gA-G]", $texto) ? "" : "não ") .
    " inicia com uma letra entre 'a' e 'g' , maiúscula ou minúscula<BR>";
  echo (ereg("^[0-9]$", $texto) ? "" : "não ") .
    " é um número de 1 dígito apenas<BR>";
  echo (ereg("^[0-9][0-9]$", $texto) ? "" : "não ") .
    " é um número de 2 dígitos apenas<BR>";
  echo (ereg("^[0-9]+$", $texto) ? "" : "não ") .
    " é um número com pelo menos 1 dígito<BR>";
  echo (ereg("^[0-9]{4}$", $texto) ? "" : "não ") .
    " é um número com exatamente 4 dígitos<BR>";
  echo (ereg("^[0-9a-zA-Z]{6}$", $texto) ? "" : "não ") .
    " se compõe de exatamente 6 números e letras (não se aceitam símbolos ou 
    pontuações)<BR>";
  }
  else echo "Digite algo na caixa de texto...";
?>
</body>
</html>

        Logo de início temos o código  <?php echo $PHP_SELF; ?> dentro de action= do formulário. Normalmente colocaríamos "tutorial11.php", mas aqui é mostrado o conteúdo de uma variável. $PHP_SELF é uma variável pré-definida do PHP, cujo valor é o endereço do arquivo PHP sendo executado. Assim, o resultado final é exatamente o mesmo, já que o valor retornado, neste caso, é "tutorial11.php". A vantagem é que o código fica mais "portável". Caso o nome do arquivo seja alterado, ele continuará funcionando normalmente, já que a variável $PHP_SELF terá seu valor corretamente ajustado.

        Note que, por padrão, todas as variáveis pré-definidas estão em maiúsculas, ao contrário das variáveis comuns. Para uma lista completa das variáveis pré-definidas veja o manual do PHP. Para uma lista das variáveis disponíveis (que depende do tipo de servidor HTTP e módulos instalados) e muitas outras informações úteis utilize a função phpinfo(). (Exemplo: <?php echo phpinfo() ?>)

        A seguir temos o código <?php echo isset($texto) ? $texto : "" ?>, que definirá o valor default que aparecerá na caixa de texto. Este código é o chamado "ternary conditional operator" traduzido muitas vezes como "expressão ternária" ou "operador condicional ternário", comum também em várias outras linguagens. Por exemplo, a expressão $primeiro ? $segundo : $terceiro retorna o conteúdo de $segundo caso $primeiro seja verdadeiro, ou o conteúdo de $terceiro em caso contrário. Assim, o código anterior retorna o conteúdo da string $texto caso ela exista (isto é, caso o programa já tenha sido executado e já tenha sido apertado o botão, rotornando o valor digitado anteriormente como default) ou retorna uma string vazia caso $texto não tenha sido definido (isto é, na primeira vez que o programa está sendo executado)

        Vamos finalmente à parte das regular expressions, termo traduzido muitas vezes como "expressões regulares". Entendam aqui a palavra regulares como algo que aconteça regularmente, ou seja, de forma comum, constante, rotineira. Logo de início é usado o código ereg("a", $texto) ? "tem ao menos uma letra a minúscula" : "não tem nenhuma letra a minúscula". Neste primeiro uso da função ereg, é verificado se $texto contém em algum lugar a string "a". Caso seja achado, a função retorna TRUE, e logicamente FALSE em caso contrário. Até aqui, fácil, não ? Esta função procura uma string dentro de outra.

        Logo a seguir, em echo (ereg("^a", $texto) ? "" : "não ") . "inicia com a letra a <BR>", é utilizado o símbolo "^", que nas "regular expressions" tem o significado especial de início da string. Assim, o resultado deste ereg é TRUE caso $texto inicie com a letra "a" minúscula, e não mais caso a contenha em qualquer lugar.

        Do mesmo modo é utilizado o símbolo "$", só que aqui representa o final da string. Assim, ereg("a$", $texto) retorna TRUE caso a string termine com a letra "a" minúscula. 

        Todos os outros exemplos são conseqüências do que foi estudado até agora, sendo que eregi faz a pesquisa de forma "case insensitive", ou seja, ignorando se a seqüência de caracteres procurada é maiúscula ou minúscula. Temos também os colchetes, que simbolizam qualquer dos caracteres de uma seqüência. Assim, [1-4] faz a pesquisa pelos caracteres 1, 2, 3 ou 4. Da mesma forma, [a-z] pesquisa qualquer letra minúscula, [A-Za-z] qualquer letra minúscula ou maiúscula, [0-9A-Za-z] qualquer dígito ou letra (não pesquisa símbolos como +, -, etc). 

        Vá acompanhando o código e executando o programa para entender melhor. Além disso, pode-se também utilizar o símbolo "+", que significa "uma ou mais ocorrência", e também as chaves "{x}", onde x representa o número exato de ocorrências.

        Este assunto é bastante extenso. Vamos prosseguir com mais um programa exemplo:

Arquivo: tutorial12.php
<html>
<body>

<form method="post" action="
<?php echo $PHP_SELF; ?>">
Texto: <input type=text name="texto" value="
<?php echo isset($texto) ? $texto : "" ?>
">
<input type=submit value="Aperte o botão !">
</form>

<?php

if (isset($texto)) {
  echo "O texto :<BR>";
  echo (ereg("a+b+", $texto) ? "" : "não ")
    . "tem um ou mais 'a' seguido por um ou mais 'b'<BR>";
  echo (ereg("a+b*c+", $texto) ? "" : "não ")
    . "tem um ou mais 'a' seguido por zero ou mais 'b' seguido por um ou mais 'c'<BR>";
  echo (ereg("a+b?c+", $texto) ? "" : "não ")
    . "tem um ou mais 'a' seguido por zero ou um 'b' seguido por um ou mais 'c'<BR>";
  echo (ereg("^a+b?c+", $texto) ? "" : "não ")
    . "inicia com um ou mais 'a' seguido por zero ou um 'b' seguido por um ou mais 'c'<BR>";
  echo (ereg("a+b{3}c+$", $texto) ? "" : "não ")
    . "finaliza com um ou mais 'a' seguido por exatamente três 'b' seguido por um ou mais 'c'<BR>";
  echo (ereg("^a+b{4,6}c+", $texto) ? "" : "não ")
    . "inicia com um ou mais 'a' seguido por quatro a seis 'b' seguido por um ou mais 'c'<BR>";
  echo (ereg("^a+b{3,}c+", $texto) ? "" : "não ")
    . "inicia com um ou mais 'a' seguido por três ou mais 'b' seguido por um ou mais 'c'<BR>";
  echo (ereg("^a+(php){3,}c+", $texto) ? "" : "não ")
    . "inicia com um ou mais 'a' seguido por três ou mais 'php' seguido por um ou mais 'c'<BR>";
  echo (eregi("^[a-z0-9]+@[a-z0-9]*$", $texto) ? "" : "não ")
    . "inicia com um ou mais caracteres seguido por um '@' seguido por zero ou mais caracteres<BR>";
  echo (eregi("^[a-z0-9]+@(php|perl)$", $texto) ? "" : "não ")
    . "inicia com um ou mais caracteres seguido por um '@' seguido por 'php' ou 'perl'<BR>";
  echo (eregi("f.w", $texto) ? "" : "não ")
    . "tem um 'f' seguido por um caracter qualquer seguido por um 'w'<BR>";
  }
  else echo "Digite algo na caixa de texto...";
?>
</body>
</html>

        O código acima mostra mais alguns símbolos utilizados nas "regular expressions" :

        Não podemos esquecer também que para pesquisar os caracteres acima (exemplo : pesquisar um ponto) precisamos utilizar a barra invertida (escaped characters)

        Vamos agora a exemplos práticos:

Arquivo: tutorial13.php
<html>
<body>

<form method="post" action="
<?php echo $PHP_SELF; ?>">
Texto: <input type=text name="texto" value="
<?php echo isset($texto) ? $texto : "" ?>
">
<input type=submit value="Aperte o botão !">
</form>

<?php

if (isset($texto)) {
  echo "O texto :<BR>";
  echo (ereg("^[0-9]+$", $texto) ? "" : "não ")
    . "é um número sem casas decimais<BR>";
  echo (ereg("^[0-9]+,[0-9]{2}$", $texto) ? "" : "não ")
    . "é um número com duas casas decimais (separadas por vírgula)<BR>";
  echo (ereg("^[0-9]+(,[0-9]+)?$", $texto) ? "" : "não ")
    . "é um número com ou sem casas decimais (separadas por vírgula)<BR>";
  echo (ereg("^[0-9]{1,3}\.[0-9]{3}(,[0-9]+)?$", $texto) ? "" : "não ")
    . "é um número maior ou igual a 1.000 e menor que 999.999 com separador de milhares (ponto) com ou sem casas decimais (separadas por vírgula)<BR>";
  echo (ereg("^[0-9]{1,3}(\.[0-9]{3})*(,[0-9]+)?$", $texto) ? "" : "não ")
    . "é um número qualquer com separador de milhares (ponto) caso seja maior ou igual a 1000 com ou sem casas decimais (separadas por vírgula)<BR>";
  echo (ereg("^[0-9]{1,3}(\.?[0-9]{3})*(,[0-9]+)?$", $texto) ? "" : "não ")
    . "é um número qualquer com ou sem separador de milhares (ponto) caso seja maior ou igual a 1000 com ou sem casas decimais (separadas por vírgula)<BR>";
  echo (eregi("^[_\-\.0-9a-z]+@[_\-\.0-9a-z]+$", $texto) ? "" : "não ")
    . "é um e-mail válido (aceita letras, números, '_', '-' e '\.'<BR>";
  echo (ereg("^[0-9]{2}\.[0-9]{3}\.[0-9]{3}/[0-9]{4}\-[0-9]{2}$", $texto) ? "" : "não ")
    . "é um CNPJ válido (exemplo: 12.345.678/0001-95 (dígito verificador não calculado)<BR>";
  echo (ereg("^([0-9]{3}\.){2}[0-9]{3}-[0-9]{2}$", $texto) ? "" : "não ")
    . "é um CPF válido (exemplo: 123.456.789-09 (dígito verificador não calculado)<BR>";
  }
  else echo "Digite algo na caixa de texto...";
?>
</body>
</html>

        Os exemplos práticos acima não apresentam qualquer símbolo novo. Qualquer dúvida reestude o que foi apresentado em tutorial11 e tutorial12.

        Conforme descrito no início desta página, vamos agora passar ao estudo das funções que chamei de "irmãs" da ereg(). Elas são:

        Além disso, ereg() pode ter um terceiro parâmetro, que é um array que vai conter exatamente dez elementos, sendo o primeiro igual ao próprio texto e os outros conforme uma separação dada na $expressão_regular feita por parênteses. 

        Vamos estudar tudo isto no próximo exemplo: (a função PHP var_dump mostra todas as informações sobre uma variável - no caso vai mostrar os 10 elementos do array)

Arquivo: tutorial14.php
<html>
<body>

<form method="post" action="
<?php echo $PHP_SELF; ?>">
Texto: <input type=text name="texto" value="
<?php echo isset($texto) ? $texto : "" ?>
">
<input type=submit value="Aperte o botão !">
</form>

<?php

if (isset($texto)) {
  echo "O texto :<br>";
  echo (ereg("^[0-9]{2}/[0-9]{2}/[0-9]{4}", $texto, $regs) ? "" : "não ")
    . "é uma data no formato DD-MM-AAAA<br>";
  var_dump($regs);
  echo "<br>";
  echo (ereg("^([0-9]{2})/([0-9]{2})/([0-9]{4})", $texto, $regs) ? "" : "não ")
    . "é uma data no formato DD-MM-AAAA<br>";
  var_dump($regs);
  echo "<br>";
  echo "este é o texto acima com as vírgulas substituídas por pontos:<br>";
  echo ereg_replace("," , "." , $texto) . "<br>";
  echo "este é o texto acima com os pontos substituídos por vírgulas:<br>";
  echo ereg_replace("\." , "," , $texto) . "<br>";
  echo "este é o texto acima com os pontos substituídos por vírgulas e vice versa:";
  echo "(isto é útil para converter números em formato 'inglês' para 'latino'<br>";
  echo ereg_replace("@@p@@", "," , ereg_replace("," , "." , ereg_replace("\." , "@@p@@" , $texto))) . "<br>";
  echo "Se o que foi digitado acima tratar-se de um diretório (dividido por /), ele é dividido assim:<br>";
  $regs = split ("/", $texto);
  var_dump($regs);
  echo "<br>";
}
else echo "Digite algo na caixa de texto...";

?>
</body>

        No último exemplo de ereg_replace, para poder fazer o "vice_versa" foi feito o seguinte:

  1. Os pontos foram substituídos pela string "@@p@@" (se você não gostos, escolha outra a seu gosto!)
  2. As vírgulas foram substituídas por pontos
  3. A string "@@p@@" foi substituída por vírgulas

        Se na etapa 1 os pontos fossem substituídos por vírgulas diretamente, a etapa 2 estragaria todo o processo.

        Esta página foi pesada, hein ? O pior é que este assunto é ainda mais extenso. Caso ache necessário, consulte as documentações já mencionadas. Mas entendo que o que foi estudado por aqui é suficiente para a compreensão da grande maioria dos programas PHP que utilizam estas funções.

próximo arquivo: tutorial1g - Arrays

©2000 por Paulo Marote paulomarote@altavista.com