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?

Mateus
fonte
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: %%.

limc
fonte
14

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

str = str.replace("%", "%%");
Cavaleiro
fonte
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)", "%%");
Toilal
fonte
-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.)

Lee Winder
fonte
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