style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Programa para probar expresiones regulares en Java

Las expresiones regulares son extremadamente útiles, pero un tanto difíciles de dominar. Y aunque la clase java.util.regex.Pattern tiene una buena descripción de como usarlas, siempre hace falta ( al menos a mí ) algo con que probarlas.

Si le aunamos a que al escribir una expresión regular y pasarla a código hay que "escapar" la diagonal invertida, se puede convertir un tanto latoso, estar a prueba y error la expresión que queremos.

Hice el siguiente programa que además ayuda a general un string copy/paste-teable para usarlo en el código cuando la expresión correcta ha sido encontrada.

Espero que a alguién le ayude.

import java.util.regex.*;
/**
 * Utilería para probar expresiones regulares
 * Por: oscarryz
 */

class TestRegex {
  public static void main( String ... args ) {
    if( args.length != 2 ) {
      System.err.println("Usar: java TestRegex pattern teststring");
      return;
    }
    String pattern    = args[0];
    String testStrign = args[1];

    Matcher matcher   = Pattern.compile( pattern ).matcher( testStrign );

    System.out.printf("\"%s\" =~ %s ? %s %n" ,
                pattern.replaceAll("\\\\","\\\\\\\\"),
                testStrign,
                matcher.matches());

    for( int i = 1 ; matcher.matches() && i <= matcher.groupCount() ; i++ ) {
      System.out.println( "group["+i+"] = "+matcher.group( i ) );
    }
  }
}

Un ejemplo de uso:

javac TestRegex.java
java TestRegex "\d" "a"
"\\d" =~ a ? false
java TestRegex "\d" "1"
"\\d" =~ 1 ? true
java TestRegex  "\w+@\w+\.\w{3}"  "user@server.com"
"\\w+@\\w+\\.\\w{3}" =~ user@server.com ? true
java TestRegex  "(\w+)@\w+\.\w{3}"  "user@server.com.mx"
"(\\w+)@\\w+\\.\\w{3}" =~ user@server.com.mx ? false
java TestRegex  "(\w+)@\w+\.\w{3}"  "user@server.com"
"(\\w+)@\\w+\\.\\w{3}" =~ user@server.com ? true
group[1] = user

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

groovysh, BeanShell

BeanShell es muy útil para esos casos, porque puedes nada más crear los patrones y probarlos sin tener que hacer un programa (es como hacerlo al vuelo y luego se desecha). Cuando tengo que probar regex últimamente uso groovysh, es bastante práctico por las facilidades que tiene precisamente para regex. Por ejemplo aquí pruebo una regex (mal hecha):

Groovy Shell (1.7.5, JVM: 1.6.0_22)
Type 'help' or '\h' for help.
-----------------------------------------------------------------------------------------------------------------------
groovy:000> "2010-01-01" ==~ /[12]\d{3}-[01]\d-[0123]\d/
===> true
groovy:000> "3010-01-01" ==~ /[12]\d{3}-[01]\d-[0123]\d/
===> false
groovy:000> "2010-41-01" ==~ /[12]\d{3}-[01]\d-[0123]\d/
===> false
groovy:000> "2010-13-01" ==~ /[12]\d{3}-[01]\d-[0123]\d/
===> true
groovy:000> "2010-13-41" ==~ /[12]\d{3}-[01]\d-[0123]\d/
===> false
groovy:000> "2010-13-39" ==~ /[12]\d{3}-[01]\d-[0123]\d/
===> true
groovy:000> 

Supongo que el problema con

Supongo que el problema con BeanShell es el mismo que con Java, tienes que andarle poniendo los \\ a los \\

Ejemplo para matchear "\\server" ( cuyo regex "natural" sería: /^\\\\\w+$/ ) En java tienes que escribir algo como "\\\\\\\\\\w+" o algo asi jajajaj te vuelves loco de inmediato :)

Groovy está groovy...

¿Sabes si la regex de Groovy

¿Sabes si la regex de Groovy es como la de Java? En el sentido que ( chafamente, quizá ) la de java lo evalua como si escribieras con /^ y $/ ?

Por ejemplo en Java la expresion "\d" da false para "a1b", mientras que para Ruby ( de donde espero Groovy copio el comportamiento ) da true.

Es decir, "\d" en Java equivale a /^\d$/ en Ruby

Y para hacer en java lo mismo que /\d/ hace en Ruby hay que escribir  ".*\d.*" en Java

Es por eso que la literal de regex en Ryz será /^$/ :) http://code.google.com/p/ryz/source/browse/test-resources/03.attributes/...

Imagen de ezamudio

groovy regex

Es que en Groovy si escribes una cadena usando diagonales en vez de comillas, sigue siendo a fin de cuentas una cadena, pero ya no tienes que escapar las diagonales inversas. Y el operador ==~ es como el String.match(). Y puedes convertir cualquiera cadena a un Pattern. Pero no te salvas de usar doble \\ para indicar una \ incluso con las diagonales:

def pat = ~/\\\\\w+/ as Pattern
//Aquí sacamos un Matcher
Matcher m = pat.matcher('cadena que contiene \\\\server y mas cosas y otro \\\\servidor y bla')
//Y del matcher podemos pedir cosas bien fácil
assert '\\\\server' == m[0]
assert '\\\\servidor' == m[1]

cool, eh?

Cool no.. Grooovy :) Y sobre

Cool no.. groooooovy :) Y sobre lo de ^$ psss ya que tienes el Groovy shell abierto ;)

Imagen de ezamudio

Equivalencias

"\d" en Java es una cadena inválida. Pero "\\d" en Java equivale a ~/\d/ en Groovy. Solamente es azúcar sintáctica (bastante dulce la neta), para evitar que tengas que escapar las \. O sea puedes usar ~/cadenas/ sin tener que usar expresiones regulares...

groovy:000> "a1b" ==~ /\d/
===> false
groovy:000> "a1b" ==~ /.*\d.*/
===> true
groovy:000> (~/\d/ as java.util.regex.Pattern).matcher("a1b")[0]
===> 1

Yap.. si igual que en Java.

Yap.. si igual que en Java. Cuando digo "\d" no me refería a la literal de string en Java, sino al valor de la expr.

Ej:

 
Pattern.compile(args[0] );

Funciona si desde la linea de comandos le mandas "\d" como primer argumento.

Lo que si no está Cool ( ni groovy ) ni en Java ni en Groovy es que force el /^$/ lo que causa un poco más de ruido es que en Groovy cuando escribes /a/ en relidad estas escribiendo /^a$/...

En fin. si, super chido nevertheless

Imagen de ezamudio

match

Lo que pasa es que String.matches y Matcher.matches() hacen el match del patrón contra la secuencia completa. Lee la documentación... si quieres que te diga si hay de la expresión en cualquier posición, entonces debes usar Matcher.find().

groovy:000> (~/a/ as java.util.regex.Pattern).matcher("hola").matches()  
===> false
groovy:000> (~/a/ as java.util.regex.Pattern).matcher("hola").lookingAt()
===> false
groovy:000> (~/a/ as java.util.regex.Pattern).matcher("hola").find()     
===> true
Imagen de alejandro jaramillo rendon

Hablando de expresiones regulares

Les adjunto este link, depronto algun dia es util http://code.google.com/p/xeger/

No se si lo conoce!!!

Un saludo

Mmhh ya veo. ( Me acabo de

Mmhh ya veo, muuuuy interesante.

( Me acabo de dar cuenta que IntellJ trae opción para Grooviear )

s = "a1b2c"
p = ~/\d/
println s ==~ p
m = s =~ p
while( m.find() ) {
  println m.group()
}

Sale

false
1
2

Y p = ~/^\d$/

Sale false nada más, como se espera.

Mmhhh no se.... Entiendo que esto lo saca directamente de Java.

La cosa se complica ( para mí :P )

Imagen de ezamudio

sí, de Java

Está usando las mismas clases de java.util.regex, no trae nada nuevo (no tendría caso). Lo único novedoso ahí es la sintaxis de las diagonales, pero te digo, eso no es más que azúcar sintáctica para facilitar el uso de regex porque sabes que tienes muchas cosas como \w \d etc.

ahhh el azúcar sintáctico..

ahhh el azúcar sintáctico.. yummi .... Al final todo es azúcar sintáctico de los rayos del sol. Groovy lo es de Java, Java de la JVM, la JVM de C++, C++ de C, C del ensamblador, el ensamblador de .. ejem, de... 0's y 1's y así hasta el infínito.

Aaaaun así, no me late que "a1b" ==~ /\d/ de false, pero la diferencia es que ahora entiendo porque. :) :)

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">