Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

José Enésio

Tutorialzão sobre expressões regulares

Recommended Posts

Tutorial sobre Expressões Regulares

 

Olá pessoal! Escrevi esse tutorialzão faz um tempinho, vou dividir ele com vocês! Desculpa pelo gigantesco tamanho das fontes é que eu escrevi ele já voltado para um outro fórum onde as fontes são um pouco menores. Mas dei uma diminuida leve no tamanho delas pra não ficar muito ruim hehe!

Nesse tutorial eu vou deixar vocês já sabendo como é que funciona e o que elas tem a oferecer. Também vou explicar os modificadores e a sintaxe. Boa sorte!

 

Índice

1.0 - O que é e para que serve

2.0 - Funções PCRE

--2.1 - preg_match()

----2.1.1 - preg_match_all()

--2.2 - preg_replace()

--2.3 - preg_split()

3.0 - Testando no JavaScript

--3.1 - String.match();

--3.2 - String.replace();

--3.3 - String.split();

4.0 - Entendendo as Patterns

--4.1 - Delimitadores

--4.2 - Modificadores de Padrão

--4.3 - Sintaxe

----4.3.1 - Subpatterns ()

------4.3.1.1 - Referências $n

------4.3.1.2 - Requerimento sem captura ?:

------4.3.1.3 - Back references \n

----4.3.2 - Classes de caracteres []

------4.3.2.1 - Negação de classe ^

----4.3.3 - Quantificadores * + ? {}

----4.3.4 - Tipos de caracteres genéricos \D

----4.3.5 - Assegurar a posição do padrão ^ $

----4.3.6 - Textos alternativos |

----4.3.7 - O coringa .

--4.4 - Escapando caracteres

5.0 - Uso prático

 

1.0 - O que é e para que serve?

 

Expressões Regulares é uma forma avançada de mexer com strings. Ela permite que você crie condições para que um trecho seja encontrado, substituído ou uma string separada em uma array. Você pode decidir substituir um BBCode em tags HTML, mas não antes de verificar se os dados dessa BBCode correspondem ao que você deseja, por exemplo. Exemplificando mais ainda, você pode verificar se o texto contido em uma BBCode img é uma URL apontando para uma imagem, por exemplo. Você pode definir para caso o usuário poste mais de 3 pontos de exclamação, então esses pontos de exclamação são retirados até ter somente 3. Como pode-se perceber, a utilidade do RegExp é apenas limitada pela sua imaginação.

 

2.0 - Funções PCRE

 

Ou Perl-Compatible Regular Expressions, essas são as funções que estaremos usando nesse tutorial. Quem quiser saber mais sobre as funções PCRE, visite o Manual do PHP. As funções que estaremos utilizando aqui são as funções preg_match(), preg_replace(), preg_split() e preg_match_all(). Calma, irei explicar cada uma delas antes de prosseguir! Não precisa tentar entender os padrões (patterns) por enquanto, irei explicar eles melhor mais tarde.

 

2.1 - preg_match()

 

A função preg_match() serve para encontrar um texto dentro de uma string. Ela irá retornar 0 caso não encontre, ou 1 caso encontre. A sintaxe básica da função é preg_match($pattern, $subject). $pattern é o padrão regexp que será testado contra a string $subject. Exemplo:

preg_match("/gat(a|o)/", "gato de rua"); -> retorna 1

 

2.2.2 - preg_match_all()

 

A função preg_match_all() funciona da mesma maneira que a preg_match(), porém ao invés de retornar 0 ou 1, ela retorna o número de vezes que o texto foi encontrado na string. É a mesma sintaxe. Exemplo:

preg_match_all("/[0-9]+/", "100 200 300 400"); -> retorna 4

 

2.4 - preg_replace()

 

A função preg_match serve para encontrar um texto dentro da string, e trocar esse texto por outro. Ela irá retornar o texto mudado. A sintaxe básica é preg_replace($pattern, $replacement, $subject). Essa função procura pelo padrão $pattern na string $subject e retorna a string com os pedaços que batem com o padrão trocados por $replacement. Exemplo:

preg_replace("/\[neg](.*?)\[\/neg]/", "<b>$1</b>", "[neg]BBCode negrito[/neg]"); -> retorna <b>BBCode negrito</b>

 

2.5 - preg_split()

 

É uma função não tão utilizada quanto às outras. Funciona como um explode() com expressões regulares. A sua sintaxe é: preg_split($pattern, $subject). Irá procura o padrão $pattern na string $subject, e irá retornar uma array separada pelo padrão. Exemplo:

preg_split("/(\.|\,)/", "100.200,300"); -> retorna array(100, 200, 300);

 

3.0 - Testando no JavaScript

 

Isso mesmo, o nosso irmãozinho menor o JavaScript, também pode realizar expressões regulares! As sua sintaxe é bem parecida, senão igual, à sintaxe que será apresentada aqui nesse tutorial. Portanto, se não tem tempo para realizar o upload de arquivos no servidor, então pode usar os métodos do objeto String, match(), replace() e split(). Note que não é necessário passar uma expressão regular como parâmetro para essas funções, você pode mandar uma string normal, e será realizada uma comparação normal de texto, é legal saber que essas funções realizam dois trabalhos em uma função só.

 

3.1 - String.match()

 

A função String.match() realiza a mesma função que a preg_match(). A sintaxe é simples, defina uma variável de texto, e use o método dessa maneira: minha_variavel.match(expressao). Em expressao você passa o padrão que deseja testar contra a string. O valor retornado será uma array de strings encontradas.

 

3.2 - String.replace()

 

A função String.replace(), como já é fácil perceber, realizará a mesma função que preg_replace(), mas novamente partindo de uma variável String. A sintaxe é minha_variavel.replace(expressao, trocar). expressao é o padrão que será testado contra a string, e troca é pelo que trocar as partes encontradas.

 

3.3 - String.split()

 

A função String.split() é uma preg_split() do JavaScript. A sintaxe é minha_variavel.split(expressao), você já deve saber o que é expressao agora. Será retornada uma array de strings, que foi separada da string principal.

 

4.0 - Entendendo as Patterns

 

As Patterns, ou padrões, são o coração do nosso código de RegExp. É bem complexo, e talvez você não entenda tudo de uma vez, mas farei o possível para você entender direitinho.

 

4.1 - Delimitadores

 

Uma pattern PRECISA ter delimitadores. Eles separam o que deve ser testado contra a string dos modificadores de padrão. O delimitador pode ser /, @ ou qualquer que seja o caractere que você queira usar, desde que não seja alfanumérico (letra ou número) ou contra-barra (\). Você pode delimitar por (), {}, [] ou <> também. Se o caractere for aparecer dentro da expressão, deve ser usada uma contra-barra para impedir que a expressão seja quebrada e ocorram erros ou comportamentos inexperados. A string de expressão deve começar com o primeiro delimitador, então a expressão vai logo após. Então será seguido do segundo delimitador, e então vem os modificadores. Exemplo de expressão:

"@(.*?)@m"

 

4.2 - Modificadores de Padrão

 

Um modificador de padrão é um caractere que é adicionado após o delimitador final que irá mudar o jeito como a função irá tratar a expressão. Esses são os modificadores, podem ser combinados da maneira que você quiser:

i -> Não diferencia maiúsculas de minúsculas;

m -> Modo multiline: os comandos ^ e $ encontram strings antes e depois de cada newline;

s -> Faz com que o caractere . encontre newlines. Sem esse parâmetro, o . não irá bater com caracteres newline;

x -> Ignora qualquer espaço em branco (incluindo \n, \r, \t, etc...) no padrão, exceto quando escapado. Também ignora texto entre um caractere # e o próximo newline, permitindo a criação de comentários dentro de uma pattern complicada;

e -> Somente funciona com a função preg_replace, na string de replacement, você pode colocar um código PHP que será rodado como se fosse um eval(). Nesse caso, você pode colocar um strtolower($1) no replacement para deixar a primeira subpattern em minúsculas, por exemplo.

 

Também podemos definir um modificador de padrão apenas dentro de uma subpattern, iniciando essa subpattern com (?i) (trocando i pelo(s) padrão(ões) desejado(s)), por exemplo, para não ficar confuso: ((?i)abc) encontra abc e ABC, ((?s).*?) pega tudo.

 

Mais informações sobre modificadores: Manual do PHP

 

4.3 - Sintaxe

 

Agora, talvez a parte mais importante e mais complicada das expressões regulares. Vamos explicar parte por parte, reserve um tempinho seu para estudar cada um separadamente.

 

4.3.1 - Subpatterns ()

 

As subpatterns nos permite fazer duas coisas:

Localizar coisas alternativas, vamos tomar como exemplo no manual do PHP, a pattern cat(aract|erpillar|), que irá encontrar "cat", "cataract" ou "caterpillar". Sem os parênteses, iria ser encontrado "cataract", "erpillar" ou uma string vazia.

O outro uso é capturar os valores, para por exemplo mostrar valores encontrados ou definir referências que podem ser usadas na string de substituição.

Para criar uma subpattern, usamos parênteses () para definir o início e término da nossa subpattern. Então colocamos as condições, comandos, textos dentro. É necessário saber que as subpatterns são ordenadas pelo seu início, por exemplo: ((circulo|triangulo) (verde|vermelho)), se usado contra uma string "o circulo vermelho", as strings capturadas serão "circulo vermelho", "circulo" e "vermelho". Olhe para as subpatterns, e você entenderá a ordem em que as strings foram capturadas: primeiro a mais exterior pois começa antes, então primeiro a interior que começa logo após a exterior, e depois a outra interior. É difícil entender com palavras, portanto compare você mesmo.

 

4.3.1.1 - Referências $n

 

Referências são, hmm... referências para as subpatterns que podemos usar no texto de substituição durante um preg_replace(). Para usar uma referência, devemos colocar no texto de substituição $n (pode ser $1, $2, $3...). Isso irá ser substituído pelo texto capturado pela enésima subpattern na string da expressão. Exemplo mais prático:

preg_replace("/gato (preto|branco)/", "cachorro $1", "O gato preto brigou com o gato branco enquanto o dono do gato cinza estava dormindo");

O que isso retorna: o cachorro preto brigou com o cachorro branco enquanto o dono do gato cinza estava dormindo.

Note como ele preservou a subpattern que vinha depois de "gato ", efetivamente apenas trocando o animal quando se tratava de um gato preto ou branco, mas preservou o gato cinza.

 

4.3.1.2 - Requerimento sem captura ?:

 

Pode ser que você queira requerir um texto sem capturar ele. Vamos fazer uma voltinha rápida ao nosso exemplo do círculo vermelho assim como ocorre no manual do PHP.

((circulo|triangulo) (verde|vermelho)), usado contra "o círculo vermelho", irá encontrar as seguintes strings: "circulo vermelho", "circulo" e "vermelho". Mas por algum motivo talvez você queira saber que é um círculo/triângulo verde ou vermelho, mas não interessa se é um círculo ou um triângulo. Apenas interessa a cor. Para isso, usamos o operador ?: logo após o início da subpattern. Veja:

((?:circulo|triangulo) (verde|vermelho)), usado contra "o círculo vermelho", irá encontrar as strings "circulo vermelho" e "vermelho". Como se pode ver, o valor da segunda subpattern foi requerido para encontrar a string, porém seu valor não foi capturado.

 

4.3.1.3 - Back references \n

 

Para ser curto e grosso, funciona da mesma maneira que as referências da string de substituição. A diferença é que essa aqui é usada na string de expressao de qualquer função PCRE. Irá referenciar qualquer resultado de uma subpattern, mas desde que essa subpattern tenha figurado ANTES da back reference, caso contrário não vai dar certo.

 

4.3.2 - Classes de caracteres []

 

Classes de caracteres servem para nós definirmos quais caracteres devem ser encontrados. Podemos também definir intervalos de caracteres, colocando [b-n] irá encontrar qualquer caractere que está entre b e n, ou então colocando [A-Z] ou [0-9], você também irá obter efeitos parecidos. Para saber como montar um intervalo como por exemplo [A-z] ou [D-_], você terá que saber os códigos ASCII dos caracteres, já que os intervalos não são baseados em letras e números, e sim no código ASCII. Por isso que [A-z] irá encontrar também alguns caracteres que se encontram entre o alfabeto maiúsculo e o minúsculo. A letra Z possui código 90 e a letra a possui código 97, portanto existem 6 caracteres que não são letras: [\]^_`.

Quem quiser saber mais sobre o ASCII, clique aqui.

Nota que uma classe de caracteres encontra apenas UM caractere, para encontrar mais você deverá usar os quantificadores.

 

4.3.2.1 - Negação de classe ^

 

Podemos definir uma classe que encontra uma das vogais minúsculas, que seria [aeiou], mas também podemos também montar uma classe que encontra qualquer caractere MENOS as vogais minúsculas, que seria [^aeiou]. Nota que esse encontra newlines também! Bom, o caractere ^, se usado no início da classe, irá criar uma classe que é qualquer caracter menos o que for definido na classe.

 

4.3.3 - Quantificadores * + ? {}

 

Quantificadores servem para nós definirmos quantas vezes devem aparecer uma classe de caracteres, uma subpattern, um caractere, o coringa . ou uma back reference. Nós podemos quantificar com {}, que nos permite definir um intervalo entre quantas vezes algo deve aparecer. Podemos definir dois números: [aeiou]{3,5} irá encontrar entre 3 e 5 vogais. Podemos definir um só: [aeiou]{3,} irá encontrar 3 ou mais vogais. Não podemos definir um máximo só, é obrigatório definir o mínimo. Por conveniência, os quantificadores mais comuns tem abreviações, veja:

* -> é igual à {0,}

+ -> é igual à {1,}

? -> é igual à {0,1}

Para melhor entendimento, * procura por 0 ou mais vezes (ou seja, irá contar como encontrado mesmo que não tenha nada), + procura por 1 ou mais vezes (ou seja, tem que ter pelo menos uma vez), e ? é cara ou coroa, ou acha uma vez ou não acha nada.

Por padrão, os quantificadores são gananciosos, e irão encontrar o máximo possível sem fazer com que o resto da pattern falhe. Ou seja, (abc) abc (abc), se você for procurar por tudo que estiver entre ( e ), irá retornar o texto todo. Para isso, podemos usar logo após o quantificador um ? para que ele deixe de ser ganancioso. Fazendo isso, a nossa pattern ali em cima deve retornar (abc) e (abc), como esperado.

Podemos também seguir um quantificador de +, o que o tornará possessivo. Ele irá comer o máximo de caracteres possível sem voltar para encontrar o resto. Um exemplo disso, como no manual: .*abc irá igualar com "aaabc", mas .*+abc não, pois o .* irá pegar todos os caracteres (afinal, . pega geral), e não irá voltar para pegar a outra parte que é abc.

 

4.3.4 - Tipos de caracteres genéricos \D

 

Tipos genéricos de caracteres são como se fossem umas classes pré-definidas. São compostos de uma contra-barra e um caractere que irá representar qual é o tipo genérico. Esses tipos também possuem suas classes de negação, que você acessa botando uma letra maiúscula ao invés de minúscula. Veja como funciona:

 

\d -> qualquer número decimal

\D -> qualquer caractere que não seja um número decimal

\h -> qualquer caractere de espaço em branco horizontal

\H -> qualquer caractere que não seja de espaço em branco horizontal

\s -> qualquer caractere de espaço em branco

\S -> qualquer caractere que não seja de espaço em branco

\v -> qualquer caractere de espaço em branco vertical

\V -> qualquer caractere que não seja de espaço em branco vertical

\w -> qualquer caractere de letra, número ou underline (_)

\W -> qualquer caractere que não seja letra, número ou underline (_)

 

4.3.5 - Assegurar a posição do padrão ^ $

 

Os caracteres ^ e $ servem para assegurar que o local onde será encontrado a expressão ou seção da expressão seja no início ou fim da string $subject, ou no caso do modo multiline estar ativado, no início ou fim de uma linha. O jeito de entender esses comandos é utilizá-los! Vamos a um exemplo: ^abc encontra abc, abcdef, mas não encontra defabc. Já abc$ encontra defabc, abc, mas não encontra abcdef.

 

4.3.6 - Textos alternativos |

 

Vocês já devem estar carecas de saber a moral do operador |, mas eu vou explicar porque foi assim que eu planejei meu tutorial! hehe

Ele funciona assim, ele irá encontrar uma ou outra string que se encontra antes ou depois dele. (verde|vermelho) encontra verde ou vermelho. Esse foi curtinho porque você já tá fera hein!

 

4.3.7 - O coringa .

 

Finalmente, nós temos o nosso caractere coringa, o .. O ponto encontra qualquer coisa, mas por padrão ele não encontra newlines. Você tem que definir o modificador s para a sua expressão nesse caso.

 

4.4 - Escapando caracteres

 

Assim como em uma string normal do PHP, em uma expressão RegExp é necessário escapar os caracteres utilizados pelo RegExp caso você queira usá-los apenas como caracteres. . encontra qualquer caractere, \. encontra um ponto final. Também é necessário cuidar dentro de definições de classes de caracteres, se quer adicionar um ] nessa classe, deve escapá-lo exemplo: [a-zA-Z\]0-9]. Isso se aplica também se você quer utilizar o delimitador da expressão dentro da expressão, você deve escapar com contra-barra também.

 

5.0 - Uso prático

 

As expressões regulares tem o seu uso limitado apenas pela sua imaginação. Mas vamos a um exemplo bem prático, o BBCode! Veja:

 

<?php
$meuPost = nl2br($_POST["msg"]);
$pattern = array(
	"/\[b](.*?)\[\/b]/",
	"/\[i](.*?)\[\/i]/",
	"/\[img](.*?)\[\/img]/"
); //sim! pode definir arrays de coisas pra achar e/ou substituir!
$replace = array(
	"<b>$1</b>",
	"<i>$1</i>",
	"<img src=\"$1\" />"
)
echo preg_replace($pattern, $replace, $meuPost);
?>

Faça um formulário com isso, e teste você mesmo. Agora que você já conhece as expressões regulares, estude-as mais a fundo, e use-as a seu favor!

 

Espero que tenham gostado! Até a próxima pessoal!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ótimo tutorial! http://forum.imasters.com.br/public/style_emoticons/default/clap.gif

 

E já que estamos falando em ERs, vale referenciar mais alguns links, para aprofundar os estudos. http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

 

Um dos mais famosos guias sobre ERs:

http://guia-er.sourceforge.net/

 

Mais links do Manual do PHP:

http://www.php.net/manual/pt_BR/ref.pcre.php

http://www.php.net/manual/pt_BR/reference....n.modifiers.php

http://www.php.net/manual/pt_BR/reference....tern.syntax.php

 

ERs são muito úteis. É bom saber usá-las.

No começo parece difícil, mas não é tanto quanto parece. :)

 

Abraços,

Beraldo

Compartilhar este post


Link para o post
Compartilhar em outros sites

não sei exatamente onde você arrumou a informação de que "\w -> qualquer caractere de letra, número ou underline (_)" pois em meus teste o php num casegue achar "cod_usuario " se buscado por "\w", ou seja, \w refere-se apenas a a-z, pelo menos aqui.

 

Ótimo tutorial! http://forum.imasters.com.br/public/style_emoticons/default/clap.gif

 

E já que estamos falando em ERs, vale referenciar mais alguns links, para aprofundar os estudos. http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

 

Um dos mais famosos guias sobre ERs:

http://guia-er.sourceforge.net/

 

Mais links do Manual do PHP:

http://www.php.net/manual/pt_BR/ref.pcre.php

http://www.php.net/manual/pt_BR/reference....n.modifiers.php

http://www.php.net/manual/pt_BR/reference....tern.syntax.php

 

ERs são muito úteis. É bom saber usá-las.

No começo parece difícil, mas não é tanto quanto parece. :)

 

Abraços,

Beraldo

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.