Expresiones regulares en Java

A partir del JDK 1.4 se incluye el paquete java.util.regexp para hacer uso de expresiones regulares en Java. El paquete está formado por dos clases, que explicaré a continuación, la clase Matcher y la clase Pattern y por una excepción, PatternSyntaxException.

Una expresión regular es un patrón que describe a un string. Recuerdo, que sin saberlo, escribía mis primeras primeras expresiones regulares en DOS, dir *.bmp, o del *.tmp o con en SQL “nombre Like ‘*ma*’” donde el asterisco significa cualquier representa cualquier secuencia de caracteres.

En Java:

  • La clase Pattern representa una expresion regular
  • La clase Matcher es un tipo de objeto que se crea mediante la invocación del método Pattern.matcher.

Veamos un ejemplo comentado para entender su comportamiento:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {

    public static void main(String[] args) {
        String input = "www.pepë@mail.com";

        // comprueba que no empieze por punto o @

        /*
         * El caracter '\' sirve preceder a expresiones con valores de escape, así \\ equivale a \ o \{ equivale a {
         * El caracter '^' indica comienzo de una línea
         * El caracter '|' representa un O lógico
         */

        Pattern p = Pattern.compile("^\\.|^\\@");
        Matcher m = p.matcher(input);
        if ( m.find() )
            System.err.println("Las direcciones email no empiezan por punto o @");

        //comprueba que no empieze por www.
        p = Pattern.compile("^www\\.");
        m = p.matcher(input);
        if (m.find())
            System.out.println("Los emails no empiezan por www");

        // comprueba que contenga @
        p = Pattern.compile("\\@");
        m = p.matcher(input);
        if (!m.find())
            System.out.println("La cadena no tiene arroba");
               
        //Comprueba que no contenga caracteres prohibidos   
        /*
         * El caracter '+' representa una o más veces
         * El caracter '^' dentro de los corchetes es un NOT, permite encontrar cualquier carácter que NO se encuentre dentro del grupo indicado
         */

        p = Pattern.compile("[^A-Za-z0-9\\.\\@_\\-~#]+");
        m = p.matcher(input);
        StringBuffer sb = new StringBuffer();
        boolean resultado = m.find();
        boolean caracteresIlegales = false;
        while(resultado) {
            caracteresIlegales = true;
            m.appendReplacement(sb, "");
            resultado = m.find();
        }

        // Añade el ultimo segmento de la entrada a la cadena
        m.appendTail(sb);

        input = sb.toString();
        if (caracteresIlegales) {
            System.out.println("La cadena contenía caracteres ilegales que han sido suprimidos");
        }
        System.out.println("Email: " + input);
    }      

}

Para finalizar y como referencia, la siguiente tabla resume el significado de los carateres especiales utilizados para la construcción de expresiones regulares. Tener en cuenta que una expresión regular sólo puede contener (aparte de letras y números) los siguientes caracteres: < \$, ^, ., *, +, ?, [, ], \. >

Lógicos:

  • x|y: x o y.
  • xy: x seguido de y

Intervalos de caracteres:

  • [abc]: Cualquiera de los caracteres entre corchetes. Pueden especificarse rangos, por ejemplo, [a-d] que equivale a [abcd]).
  • [^abc]: Cualquier carácter que no esté los que están corchetes.

Intervalos de caracteres predefinidos:

  • .: Cualquier carácter individual, salvo el de salto de línea.
  • \d: Cualquier carácter de dígito, equivalente a [0-9].
  • \D: Cualquier carácter que no sea de dígito, equivale a [^0-9].
  • \s: Cualquier carácter individual de espacio en blanco (espacios, tabulaciones, saltos de página o saltos de línea).
  • \S: Cualquier carácter individual que no sea un espacio en blanco.
  • \w: Cualquier carácter alfanumérico, incluido el de subrayado, equivalente a [A-Za-z0-9_].
  • \W: Cualquier carácter que no sea alfanumérico, equivalente a [^A-Za-z0-9_].

Caracteres:

  • \f: Salto de página.
  • \n: Salto de línea.
  • \r: Retorno de carro.
  • \t: Tabulación.

Limites:

  • ^: Principio de entrada o línea.
  • $: Fin de entrada o línea.
  • \b: Límite de palabra (como un espacio o un retorno de carro)
  • \B: Fin de palabra.

Cuantificadores:

  • {n}: Exactamente n apariciones del carácter anterior.
  • {n,m}: Como mínimo n y como máximo m apariciones del carácter anterior.
  • *: El carácter anterior 0 o más veces.
  • +: El carácter anterior 1 o más veces.
  • ?: El carácter anterior una vez como máximo (es decir, indica que el carácter anterior es opcional).

Basado en Expresiones Regulares en Java

11 comentario en este artículoDeje el suyo
  1. stoy echando un ojillo a tu blog, muy interesante por cierto.
    Te escribo porque tengo un problemilla que no soy capaz de resolver. Te explico la situación, creo que es interesante y seguro que ayuda a más de uno.
    Tengo un String que he sacado previamente de un Fichero y tengo que encontrar las estructuras que siguen el siguiente formato para hacer una modificación:
    “text1:=text2.text3″ (pat=Pattern.compile(”[a-zA-Z_0-9]+\\:\\=[a-zA-Z_0-9]+\\.[a-zA-Z_0-9]+”); )
    En el String puede haber otras estructuras similares como por ejemplo “text1:=text2″ pero estas no deberían verse afectadas.
    La idea, que es lo que no soy capaz de conseguir es que una vez tengamos localizadas las cadenas que cumplen el patrón que se ha definido (pat) tendría que substituir el := por un ::= dejando el resto de la cadena tal y como está y sin que las otras cadenas parecidas se vean afectadas.

    Espero haberme expresado con la suficiente claridad para que me puedas echar una manita porque estoy atascadísimo!!!

    Muchas gracias!!!!

  2. Bueno…. parece que finalmente lo hemos conseguido!

    La solución consiste en asignar variables a las partes del Patrón que no queremos cambiar.
    Una variable se asigna poniendo entre parentesis la parte del patrón que queremos guardar.
    De esta manera podemos modificar unicamente parte del patron localizado dejando otra parte sin tocar.
    El problema me surgió haciendo un conversor de lenguaje de programación en el que los simbolos de asignación son distintos en el lenguaje origen (:= ) y en el lenguaje destino (::=) para el caso de acceso a un campo en concreto de la variable.
    Veamos un ejemplo:
    Matcher mat=null;
    Pattern pat=null;
    // Buscamos un patrón del tipo text1:=text2.text3 pat=Pattern.compile(“([a-zA-Z_0-9]+)\\:\\=([a-zA-Z_0-9]+)\\.([a-zA-Z_0-9]+)”);
    // Así como vemos tenemos 3 variables
    mat = pat.matcher(initialString);
    String finalString = mat.replaceAll(“$1::=$2.$3″);

    El resultado final seria text1::=text2.text3.

    Espero que esto os pueda servir de ayuda.
    Espero que haya quedado claro.

  3. Excelente aporte! Muchas gracias.

    Saludos.

  4. Buen post! Gracias por las notas!

    Pura Vida!

  5. buen post!!
    resolviste alguna de mis dudas…ahora estudiare el resto de mi codigo..

  6. Hola ojalá pudieras ayudarme con alguna idea, ya que necesito hacer el siguiente programa
    Especialmente para validar la entrada de cada linea del archivo

    Generar indice para un libro.
    Para ello debes especificar un archivo de entrada en
    la linea de comandos. El archivo de entrada tiene la informacion para el indice. Cada linea tiene la cadena
    IX: seguida de una entrada al indice encerrada en llaves, luego una numero de pagina, tambien encerrado enllaves.
    Cada ! representa un subnivel. Un rango se representa entre |( y |) Ocasionalmente, sera la misma pagina, en cuyo caso, solo debe aparecer un numero de pagina en la salida. Ejemplo de archivo de entrada:
    IX: {Series|(} {2}
    IX: {Series!geometrica|(} {4}
    IX: {Constante de Euler} {4}
    IX: {Series!geometrica|)} {4}
    IX: {Series!aritmetica|(} {4}
    IX: {Series!aritmetica|)} {5}
    IX: {Series!harmonica|(} {5}
    IX: {Constante de Euler} {5}
    IX: {Series!harmonica|)} {5}
    IX: {Series|)} {5}
    Debes validar el archivo con los datos de entrada, en caso de algun error envia un mensaje e ignora esa linea en la generacion del inndice.
    La salida con el archivo ejemplo mostrado debe ser:

    Constante de Euler: 4, 5
    Series: 2-5
    aritmetica: 4-5
    geometrica: 4
    harmonica: 5
    Usar en una version arbol binario de busqueda y en la otra una tabla de dispersion, con una funcion de dispersion que tu hayas disenado (sobre-escribe el metodo hashCode)
    y el manejo de colisiones que prefieras.
    Al final de tu programa debe aparecer una tabla en la que indicas el numero de accesos necesarios para localizar cada termino del inndice con cada una de las estructuras de datos utilizadas.
    El indice y la tabla
    comparativa deben estar en orden alfabetico, ademas en el indice las paginas deben aparecer en orden
    ascendente.

  7. Hola Aqui un metodo que dice si un String es alfanumerico
    private boolean validateSiEsAlfaNumerico(String value){
    boolean esAlfaNumerico=false;
    if (value.matches(“[A-Za-z0-9]*”)){
    esAlfaNumerico=true;
    }
    return conError;
    }

  8. Buen dia yo tengo un problema

    tengo este valor 8.254.254,01

    necesito mostrarlo de esta manera= 825425401
    puedo reemplazar la coma, pero intento eliminar los puntos(.) y no me sirve la sintaxis usada es la siguiente

    Pattern patron = Pattern.compile(“,|.”);
    // creamos el Matcher a partir del patron, la cadena como parametro
    Matcher encaja = patron.matcher(acumulado_deb);
    // invocamos el metodo replaceAll
    String resultado = encaja.replaceAll(“”);

  9. Rolando tu problema es un poco mas sencillo, se puede resolver facilmente usando StringTokenizer:

    import java.until.StringTokenizer;

    public class XXX(){
    StringTokenizer ST;
    String numero,temporal;
    public void main(){new XXX();}
    public XXX(){
    numero=”8.254.254,01″;
    ST=new StringTokenizer(numero,”.”);
    numero=”";
    temporal=”";
    while((numero=ST.nextToken())!=null){temporal=temporal+numero;}
    ST=new StringTokenizer(temporal,”,”);
    numero=”";
    while((temporal=ST.nextToken())!=null){numero=numero+temporal;}
    System.out.println(“”+numero);
    }
    }

    Espero que te sirva, asi de este modo tambien puedes usar un Switch un if o lo que necesites, seleccionando que deseas tomar de tus Strings.

  10. Escribo en este foro para pedir ayuda en un script Java que me permita resolver el siguinete problema de manejo de strings:

    Variable [texto]

    Si el string: [href="http://en.wikipedia.org/wiki/"] existe en la variable [texto] y si [href="http://en.wikipedia.org/wiki/] + los 5 caracteres siguientes es diferente a [href="http://en.wikipedia.org/wiki/File]

    Entonces: Remplaza todo lo que esta a la derecha de [href="] hasta ["] por [#]

    Si no: No hacer nada.

    El script tiene que hacer eso hasta que recorra toda la variable [texto].

    Saludos y gracias de ante mano por la buena voluntad

  11. Hola, tengo que hacer un progrma que localice las etiquetas de un codigo fuente de un html y guardar el contenido de las etiquetas en un archivo txt, que puedo hacer?

1 mención a este artículo
Deje su comentario

Por favor, ingrese su nombre

Por favor, ingrese un correo-e válido

Por favor, ingrese su mensaje

luauf.com 2012

WordPress