¿Cómo escapar% en String.Format?

445

Estoy almacenando una consulta SQL en mi archivo strings.xml y quiero usar String.Formatpara construir la cadena final en el código. La SELECTdeclaración usa un me gusta, algo como esto:

SELECT Field1, Field2 FROM mytable WHERE Field1 LIKE '%something%'

Para formatear eso, reemplazo 'algo' con% 1 $ s para que se convierta en:

SELECT Field1, Field2 FROM mytable WHERE Field1 LIKE \'%%1$s%\'

Me escapo de las comillas simples con la barra diagonal inversa. Sin embargo, no puedo escapar del signo%.

¿Cómo puedo incluir una declaración similar en mi archivo strings.xml?

Mateo
fuente
No olvides escapar del% s correctamente.
Seva Alekseyev
Estarían inyectando en su propia base de datos, sin preocupación aquí;)
Matthew
77
Bueno, incluso si se trata de su propia base de datos, es posible escribir accidentalmente consultas que hacen cosas malas. O simplemente escriba consultas que no se compilan. Preparar consultas es un buen hábito.
Rauni Lillemets
Aunque es más lento de lo String.format()que podrías considerar usar en su MessageFormat()lugar.
ccpizza

Respuestas:

926

Para escapar %, tendrá que doblar hacia arriba: %%.

limc
fuente
14

Para complementar la solución establecida anteriormente, use:

str = str.replace("%", "%%");
Cavaleiro
fuente
1
Esto reemplazará el% que ya está duplicado. Por favor lea la otra respuesta.
Toilal
1
@Toilal ¿Por qué alguien escaparía de algo que ya se ha escapado? Y si lo hiciera, ¿por qué no hacerlo? Tal vez tenía la intención de tener dos signos de%, por lo que la forma correcta de escape sería '%%%%'
David Balažic
2

Este es un reemplazo de expresiones regulares más fuerte que no reemplazará %% que ya están duplicados en la entrada.

str = str.replaceAll("(?:[^%]|\\A)%(?:[^%]|\\z)", "%%");
Toilal
fuente
-3

Aquí hay una opción si necesita escapar de varios% 's en una cadena con algunos ya escapados.

(?:[^%]|^)(?:(%%)+|)(%)(?:[^%])

Para desinfectar el mensaje antes de pasarlo a String.format, puede usar lo siguiente

Pattern p = Pattern.compile("(?:[^%]|^)(?:(%%)+|)(%)(?:[^%])");
Matcher m1 = p.matcher(log);

StringBuffer buf = new StringBuffer();
while (m1.find())
    m1.appendReplacement(buf, log.substring(m1.start(), m1.start(2)) + "%%" + log.substring(m1.end(2), m1.end()));

// Return the sanitised message
String escapedString = m1.appendTail(buf).toString();

Esto funciona con cualquier número de caracteres de formato, por lo que reemplazará% con %%, %%% con %%%%, %%%%% con %%%%%% etc.

Dejará solos los caracteres ya escapados (por ejemplo, %%, %%%% etc.)

Lee Winder
fuente
8
"No puedo creer que este no sea un problema simple resuelto por ahora" << Respondiste 6 años después de que se aceptara una solución simple.
AjahnCharles