Cómo escapar texto para expresiones regulares en Java


¿Java tiene una forma integrada de escapar texto arbitrario para que pueda incluirse en una expresión regular? Por ejemplo, si mis usuarios ingresan "$5", me gustaría coincidir exactamente con eso en lugar de un" 5 " después del final de la entrada.

Author: Matt, 2008-09-13

8 answers

Desde Java 1.5, sí :

Pattern.quote("$5");
 413
Author: Mike Stone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-04 16:29:34

Diferencia entre Pattern.quote y Matcher.quoteReplacement no estaba claro para mí antes de que vi el siguiente ejemplo

s.replaceFirst(Pattern.quote("text to replace"), 
               Matcher.quoteReplacement("replacement text"));
 96
Author: Pavel Feldman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-25 23:00:51

Puede ser demasiado tarde para responder, pero también puede usar Pattern.LITERAL, que ignoraría todos los caracteres especiales mientras formatea:

Pattern.compile(textToFormat, Pattern.LITERAL);
 24
Author: Androidme,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-17 11:09:41

Creo que lo que buscas es \Q$5\E. Ver también Pattern.quote(s) introducido en Java5.

Ver Pattern javadoc para más detalles.

 13
Author: Rob Oxspring,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-25 08:26:25

En primer lugar, si

  • se usa replaceAll ()
  • NO se usa Matcher.quoteReplacement ()
  • el texto que se sustituirá en incluye un includes 1

No pondrá un 1 al final. Mirará la expresión regular de búsqueda para el primer grupo coincidente y sub QUE en. Eso es lo que significa $1, 2 2 o 3 3 en el texto de reemplazo: grupos coincidentes del patrón de búsqueda.

Con frecuencia pongo largas cadenas de texto en .archivos de propiedades, a continuación, generar temas de correo electrónico y cuerpos de esos. De hecho, esta parece ser la forma predeterminada de hacer i18n en Spring Framework. Pongo etiquetas XML, como marcadores de posición, en las cadenas y uso replaceAll() para reemplazar las etiquetas XML con los valores en tiempo de ejecución.

Me encontré con un problema en el que un usuario ingresa una cifra de dólares y centavos, con un signo de dólar. replaceAll() se ahogó en él, con lo siguiente apareciendo en una stracktrace:

java.lang.IndexOutOfBoundsException: No group 3
at java.util.regex.Matcher.start(Matcher.java:374)
at java.util.regex.Matcher.appendReplacement(Matcher.java:748)
at java.util.regex.Matcher.replaceAll(Matcher.java:823)
at java.lang.String.replaceAll(String.java:2201)

En este caso, el usuario había ingresado "$3 " en algún lugar de su entrada y reemplazarlo todo() fue a buscar en la expresión regular de búsqueda para el tercer grupo coincidente, no encontró uno, y vomitó.

Dado:

// "msg" is a string from a .properties file, containing "<userInput />" among other tags
// "userInput" is a String containing the user's input

Reemplazando

msg = msg.replaceAll("<userInput \\/>", userInput);

Con

msg = msg.replaceAll("<userInput \\/>", Matcher.quoteReplacement(userInput));

Resuelto el problema. El usuario podría poner en cualquier tipo de caracteres, incluyendo signos de dólar, sin problema. Se comportó exactamente de la manera que esperarías.

 10
Author: Meower68,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-14 15:00:27

Para tener patrón protegido puede reemplazar todos los símbolos con "\\\\", excepto dígitos y letras. Y después de que usted puede poner en ese patrón protegido sus símbolos especiales para hacer este patrón de trabajo no como texto citado estúpido, pero realmente como un patten, pero el suyo propio. Sin símbolos especiales del usuario.

public class Test {
    public static void main(String[] args) {
        String str = "y z (111)";
        String p1 = "x x (111)";
        String p2 = ".* .* \\(111\\)";

        p1 = escapeRE(p1);

        p1 = p1.replace("x", ".*");

        System.out.println( p1 + "-->" + str.matches(p1) ); 
            //.*\ .*\ \(111\)-->true
        System.out.println( p2 + "-->" + str.matches(p2) ); 
            //.* .* \(111\)-->true
    }

    public static String escapeRE(String str) {
        //Pattern escaper = Pattern.compile("([^a-zA-z0-9])");
        //return escaper.matcher(str).replaceAll("\\\\$1");
        return str.replaceAll("([^a-zA-Z0-9])", "\\\\$1");
    }
}
 4
Author: Moscow Boy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-19 16:26:48

Patrón.quote ("blabla") funciona muy bien.

El Patrón.quote () funciona muy bien. Encierra la frase con los caracteres "\P" y "\E", y si lo hace de escape "\Q" y "\E". Sin embargo, si necesita hacer un escape de expresión regular real(o escape personalizado), puede usar este código:

String someText = "Some/s/wText*/,**";
System.out.println(someText.replaceAll("[-\\[\\]{}()*+?.,\\\\\\\\^$|#\\\\s]", "\\\\$0"));

Este método devuelve: Algunos/\s/wText*/\,**

Código por ejemplo y pruebas:

String someText = "Some\\E/s/wText*/,**";
System.out.println("Pattern.quote: "+ Pattern.quote(someText));
System.out.println("Full escape: "+someText.replaceAll("[-\\[\\]{}()*+?.,\\\\\\\\^$|#\\\\s]", "\\\\$0"));
 1
Author: Adam111p,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-31 12:38:58

^(Negación) el símbolo se usa para hacer coincidir algo que no está en el grupo de caracteres.
Info sobre negation

Expresiones regulares

 0
Author: Akhil Kathi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-22 15:00:14