Estoy tratando de convertir el String
\something\
en el String
\\something\\
uso replaceAll
, pero seguir recibiendo todo tipo de errores. Pensé que esta era la solución:
theString.replaceAll("\\", "\\\\");
Pero esto da la siguiente excepción:
java.util.regex.PatternSyntaxException: Unexpected internal error near index 1
fuente
String#replaceAll()
todos modos, puede citar la cadena de reemplazo con Matcher # quoteReplacement () :theString.replaceAll("\\", Matcher.quoteReplacement("\\\\"));
Para evitar este tipo de problemas, puede usar
replace
(que toma una cadena simple) en lugar dereplaceAll
(que toma una expresión regular). Aún necesitará escapar de las barras diagonales inversas, pero no de la manera salvaje requerida con las expresiones regulares.fuente
TLDR: utilizar
theString = theString.replace("\\", "\\\\");
en su lugar.Problema
replaceAll(target, replacement)
usa sintaxis de expresión regular (regex) paratarget
y parcialmente parareplacement
.El problema es que
\
es un carácter especial en regex (se puede usar como\d
para representar un dígito) y en String literal (se puede usar"\n"
para representar un separador de línea o\"
para escapar del símbolo de comillas dobles que normalmente representaría el final del literal de cadena).En ambos casos, para crear un
\
símbolo, podemos escapar de él (hacerlo literal en lugar de caracteres especiales) colocando adicional\
antes (como escapamos"
en literales de cadena a través de\"
).Por lo tanto, para
target
regexar el\
símbolo que representa tendrá que mantenerse\\
, y el literal de cadena que representa dicho texto deberá parecerse"\\\\"
.Entonces escapamos
\
dos veces:\\
"\\\\"
(cada uno\
se representa como"\\"
).En caso de
replacement
\
que también sea especial allí. Nos permite escapar de otros caracteres especiales$
que a través de la$x
notación, nos permite usar una parte de los datos que coinciden con expresiones regulares y que se mantienen al capturar el grupo indexadox
, ya que , como"012".replaceAll("(\\d)", "$1$1")
coincidirá con cada dígito, colocarlo en el grupo de captura 1 y$1$1
reemplazarlo con sus dos copias (lo duplicará) resultando en"001122"
.Entonces, de nuevo, para dejar de
replacement
representar\
literal, necesitamos escapar de él con adicional\
que significa que:\\
\\
parece"\\\\"
PERO ya que queremos
replacement
mantener dos barras invertidas necesitaremos"\\\\\\\\"
(cada una\
representada por una"\\\\"
).Entonces la versión con
replaceAll
puede verse comoManera más fácil
Para hacer la vida más fácil, Java proporciona herramientas para escapar automáticamente texto
target
yreplacement
partes. Entonces ahora podemos enfocarnos solo en cadenas y olvidarnos de la sintaxis de expresiones regulares:que en nuestro caso puede parecer
Aun mejor
Si realmente no necesitamos soporte de sintaxis de expresiones regulares, no nos involucremos
replaceAll
en absoluto. En cambio, vamos a usarreplace
. Ambos métodos reemplazarán todos lostarget
s, peroreplace
no involucran sintaxis de expresiones regulares. Entonces podrías simplemente escribirfuente
Tendrá que escapar de la barra diagonal inversa (escapado) en el primer argumento, ya que es una expresión regular. Reemplazo (segundo argumento: consulte Matcher # replaceAll (String) ) también tiene su significado especial de barras invertidas, por lo que deberá reemplazarlas para:
fuente
Sí ... cuando el compilador de expresiones regulares ve el patrón que le ha dado, solo ve una barra invertida (ya que el lexer de Java ha convertido la doble retroceso en una sola). Es necesario sustituir
"\\\\"
con"\\\\"
, aunque no lo crean! Java realmente necesita una buena sintaxis de cadena sin formato.fuente