viernes, 21 de octubre de 2011

Reemplazando con expresiones regulares

En ciertas ocasiones he necesitado reemplazar todas las apariciones de una cierta expresión dentro de una cadena. La última vez era necesario hacer una transformación de URLs dentro del HTML de una página obtenido con un httpclient . Una buena parte de los programadores Java con los que he trabajado conocen la función replaceAll() de java.lang.String , pero casi nunca la he visto aplicada a expresiones regulares.

Por ejemplo, imaginemos que queremos modificar todas las apariciones de /display/xxxx/yyyy como atributo en el HTML y sustituirlas por http://nocompila.com:8081/display?space=xxxx&page=yyyy , en donde xxxx e yyyy puede ser cualquier expresión alfanumérica.

Para hacer esto he llegado a ver de todo, hasta construcciones del árbol DOM del html, búsqueda de nodos con atributos href con recorridos en profundidad (nada de XPath), obtención de su valor como String, tokenización, recomposición y asignación de nuevo a través del API DOM.

Pues con expresiones regulares es muy fácil, sólo hay que hacer uso de sus matching groups : dentro de una expresión regular es posible utilizar paréntesis para envolver ciertas partes de la expresión. Y se puede usar el contenido de los paréntesis en la expresión de sustitución referenciándolo con $i , siendo i la posición del grupo de paréntesis en la expresión y comenzando a numerarlos en 1.

Para nuestro ejemplo se haría

String html = // obtener html de la url

String newHtml = html.replaceAll(  
                     "=\"/display/([^/]+)/([^\"]+)\""
                   , "=\"http://localhost:8081/display?space=$1&page=$2\"");

Fácil, ¿verdad? . El único inconveniente es coger soltura con las expresiones regulares, pero el esfuerzo suele valer la pena.

1 comentario:

  1. Desde luego sí que vale la pena, pero se me ocurren situaciones más del día a día: scripts de inserción en BD para pruebas a los que hay que añadir columnas nuevas, ficheros de mapping de hibernate a los que hay que cambiarles el paquete de las clases tras una refactorización, ficheros de propiedades a los que es necesario añadir un prefijo a todas las claves, etc.

    Todas tareas monótonas que nos harían perder mucho tiempo y que con expresiones regulares se solucionan rapidamente.

    ResponderEliminar