Como escapar% em String.Format?


445

Estou armazenando uma consulta SQL no meu arquivo strings.xml e quero usar String.Formatpara criar a sequência final no código. A SELECTdeclaração usa um like, algo como isto:

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

Para formatar, substituo 'algo' por% 1 $ s para que se torne:

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

Eu escapei das aspas simples com a barra invertida. No entanto, não consigo escapar do sinal de%.

Como posso incluir uma instrução like no meu arquivo strings.xml?


Não se esqueça de escapar do% s corretamente.
Seva Alekseyev


Eles estariam injetando em seu próprio banco de dados, nenhuma preocupação aqui;)
Matthew

7
Bem, mesmo que seja o seu próprio banco de dados, é possível escrever acidentalmente consultas que fazem coisas ruins. Ou apenas escreva consultas que não são compiladas. Preparar consultas é um bom hábito.
Rauni Lillemets

Embora seja mais lento do que String.format()você pode considerar usar MessageFormat().
Ccpizza 17/05/19

Respostas:


926

Para escapar %, você precisará dobrar-lo: %%.


14

Para complementar a solução indicada anteriormente, use:

str = str.replace("%", "%%");

1
Isso substituirá% que já foi duplicado. Por favor, leia a outra resposta.
Toilal 27/07/16

1
@ Toilal Por que alguém escaparia de algo que já escapou? E se ele quisesse, por que não fazer isso de verdade? Talvez ele pretendia ter dois sinais%, então a forma escapou correta seria '%%%%'
David Balažic

2

Esta é uma substituição de regex mais forte que não substituirá %% que já foram duplicados na entrada.

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

-3

Aqui está uma opção se você precisar escapar de vários% 's em uma string com alguns já escapados.

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

Para limpar a mensagem antes de passá-la para String.format, você pode usar o seguinte

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();

Isso funciona com qualquer número de caracteres de formatação, substituindo% por %%, %%% por %%%%, %%%%%% %%%%%%, etc.

Ele deixará qualquer caractere que já tenha escapado (por exemplo, %%, %%%% etc.)


8
"Não posso acreditar que este não seja um problema resolvido simples até agora" << Você respondeu 6 anos depois que uma solução simples foi aceita.
AjahnCharles
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.