4
Al empezar a utilizar expresiones regulares, una de las primeras situaciones con las que me top茅, es la de que algunos de los operadores cuantificadores poseen cierto comportamiento como el de ser perezosos o codiciosos al momento de hacer ‘match’ con la cadena especificada. Antes de explicar de que se trata este comportamiento, recordemos los operadores cuantificadores:
- ‘*‘ indica que la expresi贸n puede venir cero o m谩s veces,
- ‘+‘ indica que la expresi贸n puede venir una o m谩s veces,
- ‘?‘ indica que la expresi贸n puede o no venir.
Empecemos la explicaci贸n con un ejemplo escrito en php y haciendo uso de la librer铆a de expresiones regulares de php: PCRE (Compatibles con Perl).
Supongamos que tenemos analizar un c贸digo html en el cual nos interesa extraer el texto que est谩 contenido entre etiquetas ‘div’. El c贸digo html de ejemplo es :
<div>esto es un ejemplo de texto</div> <div> se mostrara como funcionan en modo perezoso o codicioso</div>
Para extraer el texto contenido en el div usamos la siguiente expresi贸n regular: <div>(.*)</div>
que utilizando php la definimos as铆:
$patron = '/<div>(.*)<\/div>/';
Utilizaremos la funci贸n preg_match_all para obtener las cadenas que concuerden con la expresi贸n regular propuesta. El script se ver铆a de la siguiente manera:
<?php
$texto = "<div>esto es un ejemplo de texto</div> <div> se mostrara como funcionan en modo perezoso o codicioso</div>";
$patron = '/<div>(.*)<\/div>/U';
preg_match_all ($patron, $texto, $matches);
echo "<pre>";
print_r($matches);
echo "</pre>";
?>
Si ejecutamos el script, podemos ver que la cadena que hace match es:
[0] => 'esto es un ejemplo de texto</div><div> se mostrara como funcionan en modo perezoso o codicioso'.
Pero este resultado no es el que esperabamos. 驴Qu茅 pas贸 aqu铆? Es ahora que podemos hablar del cuantificador codicioso, el cual trata de hacer match a la cadena m谩s grande que encuentre. Y eso fue lo que pas贸 con el script, hizo match desde la apertura de la etiqueta ‘<div>’ y debido al operador (.*) incluy贸 todo el texto intermedio sin detenerse en el primer cierre ‘</div>’, ya que sigui贸 buscando si encontraba otro cierre de la etiqueta, el cual lo encontr贸 al final de la cadena.
Entonces 驴c贸mo hacemos para que obtener el texto dentro de cada etiquetas ‘div’? Transformado el cuantificador codicioso en un cuantificador perezoso para que haga match con la cadena m谩s corta que encuentre. Y eso se puede hacer agregando ‘?’ despues de la expresion (.*). La expresi贸n regular quedar铆a entonces de la siguiente manera:
<div>(.*?)</div>
Reescribiendo el script:
<?php
$texto = "<div>esto es un ejemplo de texto</div> <div> se mostrara como funcionan en modo perezoso o codicioso</div>";
$patron = '/<div>(.*?)<\/div>/';
preg_match_all ($patron, $texto, $matches);
echo "<pre>";
print_r($matches[1]);
echo "</pre>";
?>
Lo ejecutamos y vemos que ahora ya nos devuelve unicamente el contenido que esta dentro de cada etiqueta ‘div’:
Array
(
[0] => esto es un ejemplo de texto
[1] => se mostrara como funcionan en modo perezoso o codicioso
)
Este mismo comportamiento se aplica a los dem谩s cuantificadores:
| Codicioso | Perezoso |
|---|---|
| (.*) | (.*?) |
| (.+) | (.+?) |
| (?) | (??) |
Asi que ahora podemos usarlos de manera codiciosa o perezosa seg煤n nos convenga.
Como informaci贸n adicional, las expresiones regulares PCRE de php nos ofrecen el modificador U (PCRE_UNGREEDY) para poder alterar este comportamiento, haciendo que los cuantificadores que son codiciosos de manera predeterminada, se vuelvan perezosos. Usando este modificador el patr贸n quedar铆a as铆:
$patron = '/<div>(.*)<\/div>/U';
Y eso es todo amigos… hasta la pr贸xima.
Pens茅 que este tip no me iba a ser 煤til (no trabajo mucho con expresiones regulares). Falso, hoy me sirvi贸 y bastante.