2012-05-19 128 views
17

¿Hay algún método en Java o en cualquier biblioteca de código abierto para escaparse (sin citar) un carácter especial (metacaracteres), para usarlo como una expresión regular?Escapar caracteres especiales en Java Expresiones regulares

Esto sería muy útil en la construcción dinámica de una expresión regular, sin tener que escanear manualmente cada carácter individual.

Por ejemplo, considere una expresión regular simple como \d+\.\d+ que coincide con los números con un punto decimal como 1.2, así como el código siguiente:

String digit = "d"; 
String point = "."; 
String regex1 = "\\d+\\.\\d+"; 
String regex2 = Pattern.quote(digit + "+" + point + digit + "+"); 

Pattern numbers1 = Pattern.compile(regex1); 
Pattern numbers2 = Pattern.compile(regex2); 

System.out.println("Regex 1: " + regex1); 

if (numbers1.matcher("1.2").matches()) { 
    System.out.println("\tMatch"); 
} else { 
    System.out.println("\tNo match"); 
} 

System.out.println("Regex 2: " + regex2); 

if (numbers2.matcher("1.2").matches()) { 
    System.out.println("\tMatch"); 
} else { 
    System.out.println("\tNo match"); 
} 

No es sorprendente que la salida producida por el código anterior es:

Regex 1: \d+\.\d+ 
    Match 
Regex 2: \Qd+.d+\E 
    No match 

es decir, regex1 partidos 1.2 pero regex2 (que es "dinámica" construido) no (en lugar, que coincide con la cadena literal d+.d+).

Entonces, ¿hay algún método que escape automáticamente a cada metacaracidad de expresiones regulares?

Si lo hubiera, digamos, un escape() método estático en java.util.regex.Pattern, la salida de

Pattern.escape('.') 

sería la cadena "\.", pero

Pattern.escape(',') 

sólo debe producir ",", ya que es no es un meta-personaje Del mismo modo,

Pattern.escape('d') 

podría producir "\d", ya 'd' se utiliza para denotar dígitos (aunque escape puede no tener sentido en este caso, como 'd' podría significar literal 'd', que no sería mal entendido por el interpeter expresión regular para ser algo más, como sería el caso con '.').

+0

¿Cómo sería un método tal de determinar la diferencia beween un 'd' significaba como metacarácter y una 'd' en el texto para que coincida? ('quote (" d + Dollars? ")' se convertiría en '" \\ d + \\ Dollar \\ s? "' en un método de cotización trivial.) – rsp

+0

Correcto, que es exactamente por lo que estoy pidiendo un método que escaparía personajes individuales! :-) – PNS

+0

Para escapar solo de los caracteres individuales que podría jugar con un límite de palabras, algo como: 's/\ b ([dswDSW]) \ b/\\ $ 1/g;' – rsp

Respuesta

19

No estoy 100% seguro de que esto es lo que está preguntando aquí. Si usted está buscando una manera de crear constantes que se pueden utilizar en sus patrones de expresiones regulares a continuación, sólo anteponiendo con "\\" funcionaría:

String digit = "\\d"; 

No hay Pattern método que conozco que hace esto para tú. Desafortunadamente, aunque hay "\\d" para dígitos, "\\w" para caracteres de trabajo, etc. también hay () para agrupar, + y * para repeticiones, etc. No hay una forma común de tratar cada una de las partes de una expresión regular.

En su publicación utiliza Pattern.quote(string) method.Usted probablemente sabe que esta envuelve su patrón entre "\\Q" y "\\E" por lo que puede coincidir con una cadena incluso si pasa a tener un carácter especial de expresiones regulares en ella (+, ., \\d, etc.)

+1

Sé acerca de quote() y si miras el ejemplo de salida anterior, incluye \ Q y \ E. De hecho, solo estaba buscando un método para producir la versión escapada de un personaje para una expresión regular de Java. Entonces, por ejemplo, la coma escapada seguiría siendo una coma, pero el período de escape debería convertirse en \. y así. – PNS

5

La única forma en que el matger regex sabe que está buscando un dígito y no la letra d es escaparse de la letra (\d). Para escribir el carácter de escape de expresiones regulares en java, debe escapar (para que \ se convierta en \\). Por lo tanto, no hay forma de escribir torsiones dobles para caracteres especiales de expresiones regulares.

+0

Exactamente, así que quiero un método que escape a un carácter en una cadena regex (es decir, no literal). – PNS

+0

Puede escribir su propio método 'escape()' que antepone '" \\ "' a su parámetro – Attila

+1

Para aclarar la terminología, agregar una barra invertida a un carácter no especial no se llama escape. Escribir '\ d' no significa" escapar de la letra "' d'. En cambio, crea un concepto completamente distinto, una clase de personaje que representa dígitos. Un ejemplo de escape sería su segundo caso, escribiendo '\\' para representar el carácter de barra. – AndrewF

1

acuerdo con Gray, a medida que puede necesitar que su patrón tenga ambos litrales (\ [, \]) y metacaracteres ([,]). por lo tanto, con alguna utilidad, primero debe poder escapar de todos los caracteres y luego puede agregar metacaracteres que quiera agregar en el mismo patrón.

19

de escribir este patrón:

Pattern SPECIAL_REGEX_CHARS = Pattern.compile("[{}()\\[\\].+*?^$\\\\|]"); 

y utilizarlo en este método:

String escapeSpecialRegexChars(String str) { 

    return SPECIAL_REGEX_CHARS.matcher(str).replaceAll("\\\\$0"); 
} 

A continuación, se puede utilizar de esta manera, por ejemplo:

Pattern toSafePattern(String text) 
{ 
    return Pattern.compile(".*" + escapeSpecialRegexChars(text) + ".*"); 
} 

Necesitábamos para hacer eso porque, después de escapar, agregamos algunas expresiones regex. Si no, puede simplemente usar \Q y \E:

Pattern toSafePattern(String text) 
{ 
    return Pattern.compile(".*\\Q" + text + "\\E.*") 
} 
+3

Éste no funcionó para mí (al menos en Scala), pero este sí lo hizo: '" [\\ {\\} \\ (\\) \\ [\\] \\. \\ + \\ * \\? \\^\\ $ \\\\\\ |] "' – redent84

+0

Hay una lista completa de caracteres especiales aquí: http://stackoverflow.com/a/27454382/1490986 –

0

uso

pattern.compile("\""); 
String s= p.toString()+"yourcontent"+p.toString(); 

dará como resultado yourcontent como es

Cuestiones relacionadas