Java: replaceAll y el problema del $

Recientemente he sufrido la siguiente Exception:

java.lang.IllegalArgumentException: Illegal group reference

Esta exception la obtenemos cuando intentamos hacer un String.replaceAll a un String de Java que, seguramente, contiene el caràcter especial $ (dollar sign).

Aquí el problema, que puede pasar por alto cualquier programador, es que el replaceAll de la classe String hace un replace de toda la cadena haciendose servir de expresiones regulares. Si nuestro texto original contiene el caràcter $ (carácter de final de cadena en expresiones regulares), el método String.replaceAll devuelve dicha excepción, dado que cuando encuentra este carácter, detecta final de cadena, cuando posiblemente no sea así.

Por ese motivo, lo que deberemos hacer es, si sospechamos que nuestra cadena original es susceptible de tener dicho carácter, hacerle un replace un tanto especial antes de continuar:

String originalString = "Esta es una cadena con caracteres especiales: $%&()<>";
String myString = StringUtils.replace(originalString, Matcher.quoteReplacement("$"), Matcher.quoteReplacement("//$"));
System.out.println("String original: " + originalString);
System.out.println("String modificado: " + myString);

El resultado de ejecutar el código anterior es el siguiente:

String original: Esta es una cadena con caracteres especiales: $%&()<>
String modificado: Esta es una cadena con caracteres especiales: //$%&()<>

Aquí entran en juego dos classes muy interesantes, que os paso a comentar:

  • org.springframework.util.StringUtils: package de Spring que realiza diversas tareas con Strings
  • java.util.regex.Match: creamos un matcher (con expresiones regulares) para indicar que el signo $ es un carácter especial y no un String normal

De este modo obtenemos un nuevo string, llamado myString, en el que hemos realizado un replaceAll de todos los caracteres especiales $ por //$, que es la sentencia con la que escapamos caracteres especiales en Java.

Tened muy en cuenta que si volvéis a hacer un String.replaceAll de la cadena volveréis a reproducir el error. Si tenéis que tratarla o bien consumirla, lo idoneo sería haberle aplicado la sustitución justo antes de ello.

Espero haberos ayudado!

Jordi

Share Button

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.