Introducción usando Pattern y Matcher

Esta es una introducción, bastante simple, a fin de comprender acerca de patrones. Los patrones son expresiones que podemos utilizar para buscar dentro de un texto.

Dicho de otra forma cuando creamos una “expresión regular” estamos definiendo un patrón de búsqueda para localizar cadenas de caracteres.

En java contamos con dos clases importantes para esto:

Pattern es una representación de la expresión regular que ha sido ‘compilada’ para ser utilizada. Es decir, es una expresión que define un patrón de búsqueda para nuestra cadena de caracteres.

Matcher es un objeto que surge a partir del patrón (Pattern) previamente creado al cual le pasamos la cadena en dónde deseamos realizar la búsqueda de nuestra expresión.

Necesitamos dos pasos para empezar, primero compilar nuestro patrón utilizando una expresión de búsqueda o regex.

Pattern.compile(“nuestra_expresion_de_busqueda_o_regex”)

Luego crear un matcher a partir del pattern indicando sobre qué cadena de caracteres deseamos realizar la búsqueda.

Matcher m = p.matcher(“abaaaba”);

Veamos este código

public class RegexSmall {
        public static void main(String[] args) {
                Pattern p = Pattern.compile("ab");     // pattern
                Matcher m = p.matcher("abaaaba"); // source
                while (m.find()) {
                        System.out.print(m.start() + " ");
                }
        }
}</code></pre>

En nuestro texto en dónde buscaremos (source)  los índices (como mucho en Java) empiezan en cero.

source: “abaaaba”

index:   0123456

pattern: ab

salida: 0 4

En nuestro ejemplo anterior se encontrará el patrón en la posición 0 y en la posición 4 por lo que la salida será 0 4

En general la expresión de búsqueda busca de izquierda a derecha y una vez que ha encontrado un carácter este no es reutilizado. Se dice que el carácter fue **consumido**. Por ejemplo si variamos nuestra expresión de esta forma

```java
...
Pattern p = Pattern.compile("aba”);    // pattern
Matcher m = p.matcher("abababa");     // source
...</code></pre>

El resultado seguirá siendo 0 4 porque si bien en la expresión podríamos suponer que existe en el indice 2 la expresión de busqueda, el valor ya ha sido utilizado.

abababa -> indice 0 (fueron consumidos los tres primeros caracteres)

abababa -> el indice 2 ya fue utilizado anteriormente, no se puede utilizar

abababa -> indice 4

**Grupos**

Podemos utilizar también grupos de caracteres y rangos de caracteres de esta forma

[abc] Buscará solo los caracteres a, b, c

[a-f] Buscará solo a, b, c, d, e, o f

[a-fA-F] Buscará tambien el rango entre a y f (a, b, c, d, e, o f) y tambien las mayúsculas

Note que el primero es un grupo que define sólo tres caracteres y el segundo es un rango que inicia en a y termina en f. El tercer caso es similar al segundo, incluyendo las mayúsculas

Por ejemplo si tenemos

source: &#8220;cafeBABE&#8221;

index:    01234567

pattern: [a-cA-C]

la salida será: 0 1 4 5 6.

**Utilizando Metacaracteres**

Veremos sólo algunos para entender, son los que en definitiva se necesitan a menudo y en la certificación para Java

\d Un digito

\s Un espacio en blanco

\w Un caracter (letras, digitos, o &#8220;_&#8221; (guion bajo))

. punto (dot)

Por ejemplo si tenemos

source: “a12c3e456f”

index:    0123456789

pattern: \d

la salida será: 1 2 4 6 7 8 (se han buscado solo los dígitos)

Por ejemplo si tenemos

source: &#8220;a 1 56 _Z&#8221;

index: 012345678

pattern: \w

la salida será: 0 2 4 5 7 8 (se han buscado letras, digitos y guiones bajos)

Además del los valores \d dígitos) \s (espacios en blanco) y \w (letras,dígitos, o &#8220;_&#8221; guión bajo) tenemos el punto (dot) el cual indica ‘cualquier carácter en dicha posición’.

Por ejemplo para

source: &#8220;ac abc a c&#8221;

pattern: a.c  (observemos el punto entre &#8216;a&#8217; y &#8216;c&#8217;)

la salida será: 3 7

en la posicion 3 tenemos abc (la letra b fue encontrada por el punto en nuestro pattern)

en la posición 7 tenemos a c (el espacio fue encontrado por el punto en nuestro pattern)

**Cuantificadores (quantifiers)**

Hay un grupo de regex llamados cuantificadores (quantifiers) que nos permiten definir este concepto de “cero / uno o más”.

Tenemos estos cuantificadores

  * Uno o más 
  * Cero o más ocurrencias 

? Cero o una ocurrencia

Por ejemplo para “uno o más” el cuantificador es el simbolo ‘más’ “+” que podemos utilizar de esta forma.

source: &#8220;1 a12 234b&#8221;

pattern: \d+ Buscar uno o mas digitos

la salida sera: 0 3 6

Tenemos en

0 el valor 1

3 el valor 12

6 el valor 234

Veamos este otro ejemplo para entender otro concepto llamado c**uantificador greedy y cuantificador reluctant.**

Por ejemplo si tenemos

source: yyxxxyxx

pattern: .*xx

la salida será: 0 (cero)

La salida nos indica que el resultado está en el indice 0 cero. Esto es correcto porque si observamos yyxxxyxx toda la cadena termina en ‘xx’ y lo que estamos pidiendo es ‘busque cualquier carácter (lo hemos dicho con el punto y el asterisco) que termine el xx’. Esto es lo que hace el cuantificador greedy, mira primero toda la cadena completa y luego busca de derecha a izquierda.

Ahora, si quisiéramos como resultado estos dos valores en yyxxxyxx que terminan en xx

El valor yyxx ubicado a partir del indice 0

El valor xyxx ubicado a partir del indice 4

Para este caso es cuando utilizamos el reluctant (agregando un ? al cuantificador). El cuantificador reluctant lo que hace es empezar leyendo el texto de izquierda a derecha hasta hallar la coincidencia buscada.

Si cambiamos el pattern de esta forma

source: yyxxxyxx

pattern: .*?xx

usando el reluctant *?, obtenemos lo siguiente:

0 yyxx

4 xyxx

Resumiendo lo anterior

uno o mas:    + greedy, +? reluctant

cero o mas:    _greedy,  _? reluctant

cero o uno:   ? greedy, ?? reluctant ()

<div style="font-size: 0px; height: 0px; line-height: 0px; margin: 0; padding: 0; clear: both;">
</div>
Hi! If you find my posts helpful, please support me by inviting me for a coffee :)

Ver también